Search code examples
c#windows-services

How to call a method every minute but take into account the time it takes for that method to process might take more than one?


I'm working on windows service and I want to call a method from OnStart every minute. I originally had a forever while loop but then the service wouldn't install.

while (true)
{
    Stopwatch stopWatch = new Stopwatch();
    int totalTime = 0;
    stopWatch.Start();

    MethodToCall();

    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;
    totalTime = ts.Seconds * 1000 + ts.Milliseconds;

    if (totalTime < 60000)
    {
        Thread.Sleep(60000 - totalTime);
        //ManualResetEvent.WaitOne(10000);
    }
    else
    {
        Thread.Sleep(30000);
    }
}

So, how can I make my method call every minute BUT when the method exceeds one minute it will wait N number of minutes(let's say 30 seconds) and then start over by calling the method.


Solution

  • Something like this should work. With the AutoReset flag set to false, the timer will only fire once, after the specified interval time. In the finally block, we make sure to restart the timer countdown, waiting for the interval to elapse again.

    var interval = TimeSpan.FromMinutes( 1 );
    var timer = new System.Timers.Timer( interval.TotalMilliseconds ) { AutoReset = false };
    timer.Elapsed += ( sender, eventArgs ) =>
    {
        var start = DateTime.Now;
        try
        {
            // do work
        }
        finally
        {
            var elapsed = DateTime.Now - start;
            if ( elapsed < interval )
                timer.Interval = (interval - elapsed).TotalMilliseconds;
            else
                timer.Interval = TimeSpan.FromSeconds( 30 ).TotalMilliseconds;
            timer.Start();
        }
    };
    timer.Start();
    

    Source for Timer.Elapsed (note the bit about setting Interval resetting the countdown)