简体   繁体   English

如何在特定时间的特定时间启动计时器?

[英]How to start a timer at a specific time for a specific time?

Here is the scenario: 这是场景:

There is a Textbox in which a user enters the time at which the DispatcherTimer must start. 有一个Textbox ,用户可以在其中输入DispatcherTimer必须启动的时间。 The Timer is set to run for 4 hours always and Timer.Tick event plays a sound. Timer设置为始终运行4小时,Timer.Tick事件播放声音。 Let's say the timer starts at 04:00:00 (HH:mm:ss), it should run till 8:00:00 and then stop. 假设计时器从04:00:00开始(HH:mm:ss),它应该运行到8:00:00然后停止。 Then when the user changes the time, let's say, to 09:00:00. 然后当用户改变时间时,比方说,到09:00:00。 The timer should run till 13:00:00 and so on. 计时器应该运行到13:00:00,依此类推。

How can this be achieved? 怎么能实现这一目标? I can't run a 1 minute timer that keeps checking for the right time because that will be very heavy on the system. 我不能运行1分钟的计时器来继续检查正确的时间,因为这对系统来说非常沉重。

All help is appreciated. 所有帮助表示赞赏。 Thank you in advance. 先感谢您。

The method below starts an initial timer with an interval based on the datetime supplied (ie the time entered into your textbox). 下面的方法启动一个初始计时器,其间隔基于提供的日期时间(即输入文本框的时间)。 When the the time is reached it starts a secondary timer that will fire every four hours from that point on. 当达到时间时,它启动一个辅助计时器,从该点开始每四个小时触发一次。

I used System.Timers Timer rather than the Sytem.Threading Timer (because ironically the system.threading timer is not thread safe!) 我使用System.Timers Timer而不是Sytem.Threading Timer(因为具有讽刺意味的是system.threading计时器不是线程安全的!)

    public void StartTimer(DateTime time)
    {
        const int fourHoursInMilliseconds = 4 * 3600 * 1000;

        var fourHourTimer = new Timer() {Interval = fourHoursInMilliseconds};
        fourHourTimer.Elapsed += (sender, e) =>
        {
            //code to handle the elapsed event here
        };

        var span = time - DateTime.Now;
        var timer = new Timer {Interval = span.TotalMilliseconds, AutoReset = false};
        timer.Elapsed += (sender, e) => { fourHourTimer.Start();};
        timer.Start();
    }

Hope this is what you need. 希望这是你需要的。

You have 2 problems here. 你有2个问题。

  1. How to start the timer at specified time (this is called scheduling ), see eg this . 如何开始在指定的时间计时器(这被称为调度 ),例如参见
  2. How to re-evaluate target time of possibly running timer. 如何重新评估可能运行的计时器的目标时间。

Scheduling (assuming your software will be running) is basically creating timer when user finishes his input. 调度(假设您的软件将运行)基本上是在用户完成输入时创建计时器。 If user changes time you have to stop that timer and start it again using new time. 如果用户更改时间,您必须停止该计时器并使用新时间再次启动它。

Regarding re-evaluating, same tactic: create and start new timer every time user change value, taking in account whenever timer is running and already passed time. 关于重新评估,相同的策略:每次用户更改值时创建并启动新计时器,在计时器运行且已经过时的情况下考虑。

So basically it will be 2 timers, where one is used to start another. 所以基本上它将是2个定时器,其中一个用于启动另一个。

Pseudocode: 伪代码:

 DispatcherTimer _scheduler;
 DispatcherTimer _timer;
 DateTime _start;
 TimeSpan _duration;

 // call this when specified time is changed
 void Schedule(DateTime time)
 {
     _start = time;
     // prevent any logic to run if timer is counting duration
     if(_timer != null)
         return;
     // stop scheduler
     if(_scheduler != null)
         _scheduler.Stop();
     // create new scheduler
     _scheduler = new DispatcherTimer { Interval = _start - DateTime.Now };
     _scheduler.Tick = (s, e) =>
     {
         Start(_duration); // here scheduler will start timer
         _scheduler.Stop(); // after that you don't need scheduler anymore
         _scheduler = null;
     }
     _scheduler.Start();
 }

 // call this when duration is changed
 void Start(TimeSpan duration)
 {
     _duration = duration;
     // prevent from running before starting time
     if(DateTime.Now < _start)
         return;
     // stop running timer
     if(_timer != null)
         _timer.Stop();
     // create timer to count duration including already expired time
     _timer = new DispatcherTimer { Interval = _duration - (DateTime.Now - _start) };
     _timer.Tick = (s, e) =>
     {
         ... // whatever
         _timer.Stop(); // clean up
         _timer = null;
     }
     _timer.Start();
 }

I am using DispatcherTimer to avoid invoke when starting another DispatcherTimer . 我正在使用DispatcherTimer来避免在启动另一个DispatcherTimer时调用。 Both Schedule() and Start() should be called from UI thread (eg TextChanged event handler). 应该从UI线程调用Schedule()Start() (例如TextChanged事件处理程序)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM