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

时间:2016-06-06 11:50:47

标签: c# wpf timer

以下是该方案:

Textbox用户输入DispatcherTimer必须开始的时间。 Timer设置为始终运行4小时,Timer.Tick事件播放声音。让我们说计时器从04:00:00(HH:mm:ss)开始,它应该运行到8:00:00然后停止。然后当用户改变时间时,让我们说到09:00:00。计时器应该运行到13:00:00,依此类推。

如何实现这一目标?我不能运行一个1分钟的计时器来继续检查正确的时间,因为这对系统来说非常沉重。

感谢所有帮助。提前谢谢。

2 个答案:

答案 0 :(得分:5)

下面的方法启动一个初始计时器,其间隔基于提供的日期时间(即输入文本框的时间)。当达到时间时,它会启动一个辅助计时器,该计时器将从该点开始每四个小时启动一次。

我使用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();
    }

希望这就是你所需要的。

答案 1 :(得分:1)

这里有2个问题。

  1. 如何在指定时间启动计时器(这称为计划),请参阅例如this
  2. 如何重新评估可能正在运行的计时器的目标时间。
  3. 调度(假设您的软件将运行)基本上是在用户完成输入时创建计时器。如果用户更改时间,您必须停止该计时器并使用新时间再次启动它。

    关于重新评估,同样的策略:每次用户更改值时创建并启动新计时器,在计时器运行且已经过时的时候考虑。

    所以基本上它将是2个计时器,其中一个用于启动另一个计时器。

    伪代码:

     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();
     }
    

    我正在使用DispatcherTimer来避免在启动另一个DispatcherTimer时调用。应该从UI线程调用Schedule()Start()(例如TextChanged事件处理程序)。