繁体   English   中英

定时器间隔为数月

[英]Timer with interval of multiple months

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

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

我该怎么办?

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

另一种选择是使用Windows Scheduler执行的预定作业。 它会运行一个小程序,向您的服务发送一条消息,说明事件已经发生。 这比资源密集程度更低 - 虽然更复杂 - 而不是定期醒来检查3个月是否已经过去。

您无法连续运行PC 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;
        }
    }

我会使用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

祝好运!

有同样的问题,除了它是一个通用系统可以用完全可调节的间隔做同样的事情,从几毫秒到几个月。 好吧, 应该是。 事实证明,由于这个原因,它确实在大于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和一个系统来中止外部停止命令。 但这就是它的要点。

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

暂无
暂无

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

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