【问题标题】:Timer with interval of multiple months间隔数月的定时器
【发布时间】:2010-11-26 01:04:37
【问题描述】:

我有一个 Windows 服务处理由 System.Timers.Timer 触发的事件。 我想将该计时器的间隔设置为 3 个月。

System.Timers.Timer 的 Interval 属性是以毫秒为单位的 Int32,而 Int32.MaxValue 以毫秒为单位小于 3 个月。

我该怎么办?

【问题讨论】:

    标签: c# timer


    【解决方案1】:

    遇到了同样的问题,只是它是一个通用系统,可以以完全可调的时间间隔(从毫秒到几个月)做同样的事情。嗯,是应该。事实证明,因为这个原因,它确实在大于 24.8 天的间隔上搞砸了。

    就我而言,“重新考虑方法”是不可能的,因为它只是更大的 Windows 服务系统的一个小问题子案例。

    解决方案相当简单,但请注意我有一个辅助系统,它为我提供了下一次执行为DateTime;计时器的工作只是将其与实际执行任务相匹配,因此它只需从中减去DateTime.Now 即可计算出间隔。

    在这种情况下,我需要做的就是在我的计时器对象旁边保留一个溢出布尔值,并在根据Int32.MaxValue 检查该间隔时设置它:

    private Timer _timer;
    private Boolean _overflow;
    
    private void QueueNextTime(DateTime thisTime)
    {
        TimeSpan interval = this.GetNextRunTime(thisTime) - DateTime.Now;
        Int64 intervalInt = (Int64)((interval.TotalMilliseconds <= 0) ? 1 : interval.TotalMilliseconds);
        // If interval greater than Int32.MaxValue, set the boolean to skip the next run. The interval will be topped at Int32.MaxValue.
        // The TimerElapsed function will call this function again anyway, so no need to store any information on how much is left.
        // It'll just repeat until the overflow status is 'false'.
        this._overflow = intervalInt > Int32.MaxValue;
        this._timer.Interval = Math.Min(intervalInt, Int32.MaxValue);
        this._timer.Start();
    }
    
    // The function linked to _timer.Elapsed
    private void TimerElapsed(object sender, ElapsedEventArgs e)
    {
        this._timer.Stop();
        if (this._overflow)
        {
            QueueNextTime(e.SignalTime);
            return;
        }
    
        // Execute tasks
        // ...
        // ...
    
        // schedule next execution
        QueueNextTime(e.SignalTime);
    }
    

    当然,这是简化的;真实系统有 try/catch 和一个系统,可以根据外部停止命令中止。但这就是它的要点。

    【讨论】:

      【解决方案2】:

      您会重新考虑您的设计。存储您下次要执行事件的时间(例如注册表、文件、数据库等),然后定期唤醒以检查该时间是否已过。即使您可以将 System.Timers.Timer 设置为 3 个月,系统也可能会在计时器关闭之前重新启动,并且您会丢失您的事件。

      另一种选择是使用由 Windows 调度程序执行的调度作业。它将运行一个小程序,向您的服务发送一条消息,说明事件已发生。与定期醒来检查 3 个月是否已过相比,这将减少资源密集型(尽管更复杂)。

      【讨论】:

      • 重新设计设计,现在计时器检查 NextExecuteTime 属性。感谢您的帮助。
      【解决方案3】:

      我会使用 Quartz.net - 开源企业作业调度器 - http://quartznet.sourceforge.net/

      您可以使用类似 CRON 的语法 - http://quartznet.sourceforge.net/tutorial/lesson_6.html 并且您可以轻松地将相关的工作状态存储到数据库中(以防机器死机)-http://quartznet.sourceforge.net/tutorial/lesson_9.html,还有更多用处。

      我已经在几个生产系统上使用过 Quartz.net,据我所知,这些进程今天仍在运行 :)

      为什么不使用 System.Timer - http://quartznet.sourceforge.net/faq.html#whynottimer

      祝你好运!

      【讨论】:

        【解决方案4】:

        您不能连续运行您的电脑 3 个月。如果应用程序关闭,计时器也将关闭。在重新启动应用程序时,计时器会从头开始重新启动。

        如果您想每隔 3 个月触发一次事件,您必须保留有关退出应用程序时计时器经过的总时间的信息。

        更新

        因此,您必须将间隔划分为某些部分,并在每个时间段上设置一个计数器并增加它。在每个时间段中检查它,直到达到 3 个月。

        例如

            int interval = 10 * 24 * 60 * 60 * 1000; // Time interval for 10 days 
            int counter = 0;
            private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                counter++;
                if (counter == 9) 
                {
                    //do your task for 3 months
                    //since counter increments 9 times at interval of 10 days
                    //so 9*10=90 days i.e. nearly equal to 3 months
                    counter = 0;
                }
            }
        

        【讨论】:

        • 正如我所提到的,这是针对 Windows 服务,而不是应用程序,因此我确实希望该服务能够连续运行几个月。不过感谢您的评论。
        • 您是否真的希望 Windows 机器一次能够可靠地运行 3 个月以上?即使没有崩溃,也会发布关键的安全更新,需要每隔几个月重新启动一次。查看uptime.netcraft.com/up/today/top.avg.htmluptime.netcraft.com/up/today/requested.html 的正常运行时间统计信息。许多系统的正常运行时间以周为单位,最好的以月为单位。
        • @JamesKovacs 如果计时器设置为在特定的预计算日期触发,则无关紧要。不过,它恰好需要一个时间span。您希望系统依靠停机并重新启动才能正常运行吗?
        【解决方案5】:

        我将创建一个 exe 应用程序并作为计划的 Windows 任务的一部分运行。

        【讨论】:

          猜你喜欢
          • 2021-01-24
          • 1970-01-01
          • 1970-01-01
          • 2021-10-18
          • 1970-01-01
          • 2016-03-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多