简体   繁体   中英

Timer with interval of multiple months

I have a windows service handles events triggered by a System.Timers.Timer. I want to set the interval of that timer to 3 months.

The Interval property of the System.Timers.Timer is an Int32 in millseconds, and Int32.MaxValue is smaller than 3 months in milliseconds.

What should I do?

You would re-think your design. Store the next time you want to execute your event (eg registry, file, database, ...) and then wake up periodically to check whether that time has passed. Even if you could set a System.Timers.Timer for 3 months, the system would likely reboot before the timer went off and you'd lose your event.

Another option would be to use a scheduled job executed by the Windows Scheduler. It would run a small program that sends your service a message saying that the event has occurred. This would be less resource intensive - though more complex - than waking up periodically to check whether the 3 months had elapsed.

You can't run your PC for continuously for 3 month. If application is closed timer will also close. On restarting application results the timer to restart from beginning.

If you want to fire event at interval of 3 months you must keep information about the total time elapsed by the timer at the time of exiting application.

Updated

So you have to divide your interval in some parts and set a counter on every elapse and increment it.Check it in every elapse until it reaches to 3 months.

eg

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

I would use Quartz.net - the opensource enterprise job scheduler - http://quartznet.sourceforge.net/

You may use CRON like syntax- http://quartznet.sourceforge.net/tutorial/lesson_6.html & you may store relevant job state to a DB easily (just incase the machine dies, which it will) - http://quartznet.sourceforge.net/tutorial/lesson_9.html , and lots more usefulness.

I've used Quartz.net on several production systems and to my knowledge the processes are still running today :)

Why not use System.Timer - http://quartznet.sourceforge.net/faq.html#whynottimer

Good luck!

Had the same problem, except that it was a generic system that could do the same thing with completely adjustable intervals, from milliseconds to months. Well, was supposed to. Turned out it indeed messed up on intervals larger than 24.8 days because of this.

In my case, "rethinking the approach" was of out of the question, since it was just one small problem sub-case of a much larger Windows service system.

The solution was rather simple, but do note I had a side system that supplied me with the next execution as DateTime ; the timer's job was just to match that to actually execute the task, so it calculated the interval simply by subtracting DateTime.Now from that.

In this case, all I needed to do was keep an overflow boolean alongside my timer object, and setting that when checking that interval against 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);
}

This is simplified, of course; the real system has try/catch and a system to abort on external stop commands. But that's the gist of it.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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