Today I had to implement an ASP.NET Core backgroundservice that need to execute at certain intervals. Before .NET 6 I would have used Task.Delay
or System.Threading.Timer
, but in .NET 6 we have a better alternative through the PeriodicTimer
.
The PeriodicTimer
uses an asynchronous approach based on the System.Threading.Tasks. It has a method WaitForNextTickAsync
that allows to pause execution until the next time the timer is elapsed.
I first created a backgroundservice:
class CleanupService : BackgroundService | |
{ | |
private readonly ILogger<CleanupService> _logger; | |
public CleanupService(ILogger<CleanupService> logger | |
{ | |
_logger = logger; | |
} | |
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | |
{ | |
} | |
} |
In the ExecuteAsync
method I can now introduce the PeriodicTimer
and call the WaitForNextTickAsync()
method in a while loop . The loop shall run while no cancellation of the background service is requested in the CancellationToken and wait for the next tick of the timer:
Remark: The PeriodicTimer is intended to be used only by a single consumer at a time: only one call to WaitForNextTickAsync() may be in flight at any given moment. So make sure that your business logic is executed before the interval elapses again.
private readonly TimeSpan _period = TimeSpan.FromMinutes(20); | |
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | |
{ | |
using PeriodicTimer timer = new PeriodicTimer(_period); | |
while (!stoppingToken.IsCancellationRequested && await timer.WaitForNextTickAsync(stoppingToken)) | |
{ | |
//Call our business logic | |
} | |
} |