Daniel A
Daniel A

Reputation: 77

Timer auto restart after method finished

I set a timer logic in Main program to AutorReset every 30 seconds, so my LogCollection method (which extract data) will loop every 30 seconds and my code can keep going on.

The problem is that I realized that sometimes the time given is shorter than the method execution time which cause multiple method calls at the same time which results multiple data flood.

Q: How can I make the timer wait and no to do another cycle before the method finished?

Timer code looks like:

        Timer thetimer = new Timer(TimeSpan.FromSeconds(30).TotalMilliseconds);
        thetimer.Elapsed += new System.Timers.ElapsedEventHandler(LogCollector.LogCollection);
        thetimer.AutoReset = true;
        thetimer.Start();

I was thinking to add some While loop but than my code would loop on that forever and the rest of the code would not complete. Please advise

Upvotes: 0

Views: 160

Answers (1)

Johnathan Barclay
Johnathan Barclay

Reputation: 20373

I would abandon Timer and use async instead:

while (true)
{
    var start = DateTime.Now;
    LogCollector.LogCollection();
    var timeRemaining = TimeSpan.FromSeconds(30) - (DateTime.Now - start);
    await Task.Delay(Math.Max(timeRemaining.TotalMilliseconds, 0));
}

Math.Max is used in case the execution of LogCollection() exceeds 30 seconds, in which case timeRemaining would be negative.

If you have code to run after the loop, move it into a cancellable method:

async Task LogCollectionLoopAsync(TimeSpan minLoopTime, CancellationToken ct)
{
    while (!ct.IsCancellationRequested)
    {
        var start = DateTime.Now;
        LogCollector.LogCollection();
        var timeRemaining = minLoopTime - (DateTime.Now - start);
        await Task.Delay(Math.Max(timeRemaining.TotalMilliseconds, 0), ct);
    }
}

Then your Main method could be written like this:

async Task Main()
{
    var cts = new CancellationTokenSource();

    var logCollectionTask = LogCollectionLoopAsync(TimeSpan.FromSeconds(30), cts.Token);

    // Do your other stuff

    cts.Cancel();

    try { await logCollectionTask;  } catch { } // Cancellation causes an exception
}

Upvotes: 1

Related Questions