当系统处于睡眠状态时,Windows服务中的计时器如何表现?

时间:2014-08-25 09:16:43

标签: c# timer windows-services

假设我有一个Windows服务,它有一个设置为每6小时运行一次的计时器,我希望它每天发射4次。让我们说: 0000 0600 1200 1800 。 (军事时间,与00:00等相同......)

如果系统以 1000 进入睡眠状态,并且在 1700 时醒来,会发生什么?

  1. 会再次点击 1900 ,因为计时器上有2个小时?
  2. 它会立即开火(因为它错过了 1200 预约),然后再次点击 2300 (加上它的6小时)到现在的时间?)
  3. 我注意到,当计算机进入睡眠状态时,它不会触发OnPauseOnContinue方法。

    如果有人能够在上述案例中阐明系统的行为,那就很有用了。
    干杯,并提前感谢。

2 个答案:

答案 0 :(得分:2)

正如评论中已经提到的:使用任务计划程序而不是计时器。有关进一步的讨论,请参阅this article

但是,计时器在睡眠期间的表现仍然很有趣。在您提到的特定情况下,选项2将是观察到的行为。计时器将在恢复时触发,因为它在睡眠期间错过了一个事件,然后再次从0开始计数。下一次点火将在23:00进行。 This answer有示例代码来支持观察。

如果您想要检测系统何时休眠和恢复,请订阅SystemEvents.PowerModeChanged事件。此活动的PowerModeChangedEventArgs包含Mode,您感兴趣的是SuspendResume

答案 1 :(得分:0)

根据我的需要,我最终选择了一项Windows服务,该服务将检查是否以及何时需要进行下一次操作,并将计时器设置为该时间。
Windows服务将在从睡眠状态恢复时更新该时间。

好处是:

  • 不受睡眠/觉醒时间的影响
  • 调度程序不运行任何控制台应用程序。
  • 使用NLog(快速tutorial here)和Growl(如何使用Growl与NLog教程here)在桌面上接收通知
  • 同时登录系统

由于我的案例很简单,所以功能已经在一个单独的dll中,我没有任何稳定性或内存泄漏的问题(如果我这样做,我会感到羞耻)。这样可以保持我每天需要的一次,或者每次计算机唤醒时保持一次,并且不会给系统带来额外的开销。


Henrik 一样回复并关联,正确的回答是数字2。

我在linqpad中写了以下内容,类似于上面答案中的链接:

static int counter = 0;
static System.Timers.Timer my_timer;

void Main()
{
    // Set up a timer to trigger every minute.
    my_timer = new System.Timers.Timer();

    DateTime now = DateTime.Now;
    my_timer.Interval = (60 - now.Second) * 1000; // Fire at beginning of minute
    string.Format("First tick in {0} seconds", my_timer.Interval/1000).Dump();

    my_timer.Elapsed += OnTimer;
    my_timer.Start();

    while (counter < 5) {    // sleep away until 5 ticks happen
        Thread.Sleep(5000);
    }

    // stop timer and say goodbye
    my_timer.Stop();
    DateTime.Now.Dump("Finished running, shutting down");
}

// Print time and counter every timer tick
void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
    if (my_timer.Interval != 60000) // set to one minute after first time
        my_timer.Interval = 60000; 

    DateTime.Now.ToString("HH:mm:ss.fff").Dump("On Timer fired:");
    (counter++).Dump("Static counter :");
}

获得结果:

  

首先登入:37秒

     

On Timer被解雇:08:47:00.552
  静态计数器:0

     

On Timer被解雇:08:48:00.557
  静态计数器:1

     

On Timer被解雇:08:49:00.571
  静态计数器:2

     

//在08:49:30关闭电脑3分钟

     

On Timer被解雇:08:52:33.509
  静态计数器:3

     

On Timer被解雇:08:53:33.510
  静态计数器:4

     

完成跑步,关闭   1/09/2014 8:53:38 AM

所以,显然计算机知道它错过了一个滴答声,它会触发该方法一次,并从那里继续。请注意,它只会触发一次。

如果有人知道幕后发生的事情可以为此提供更多信息,那将会很高兴。