Search code examples
c#async-awaittimerworkerperiodic-task

Executing async Task every n seconds, including the runtime of the Task itself


I have a windows service, in which I want to execute a asynchronous task every n seconds, but the time the task I am waiting for should be included in this n seconds.

Here is a short sample

CancellationToken stoppingToken = new();
while (!stoppingToken.IsCancellationRequested)
{
    await DoJob();
    await Task.Delay(5000);
}

and here the DoJob Task:

private async Task DoJob()
{
    Thread.Sleep(3000);
}

If I log the loop and the Task I can see, that the task is taking 3 seconds, and the delay afterwards 5 seconds.

Loop startet at 07.06.2024 12:01:46
Start Job at    07.06.2024 12:01:46
Ended Job at    07.06.2024 12:01:49 
Loop startet at 07.06.2024 12:01:54 
Start Job at    07.06.2024 12:01:54 
Ended Job at    07.06.2024 12:01:57 
Loop startet at 07.06.2024 12:02:02 
Start Job at    07.06.2024 12:02:02 
Ended Job at    07.06.2024 12:02:05 

How can I change this to run the task every 5 seconds INLCUDING the 3 seconds the task takes. (Of cause in real world the time the task takes is not known exactly.

And in a second step: how to check if the previous task has ended to avoid start it multiple times. (E.g. the task takes 10 seeconds an the delay is only 5 seconds ...)


Solution

  • Look at quite new PeriodicTimer

    var periodicTimer = new PeriodicTimer(TimeSpan.FromSeconds(5));
    
    while (await periodicTimer.WaitForNextTickAsync(stoppingToken))
    {
        await DoJob();    
    }