Reputation: 465
I have this BackgroundService:
public class ReminderService : BackgroundService
{
private readonly int[] reminderDays = { 1, 3, 6, 9 };
protected override async Task ExecuteAsync(CancellationToken stopToken)
{
while (!stopToken.IsCancellationRequested)
{
DateTime now = DateTime.Now;
DateTime start = now.Date.AddHours(13);
if (now > start) start = start.AddDays(1);
await Task.Delay(start.Subtract(now), stopToken);
if (reminderDays.Contains(now.Day)) await DoWork();
}
}
protected async Task DoWork()
{
// The work...
}
}
I want the service to run the first, third, sixth and ninth day each month at 1 PM. From what I can see in my log, the service rarely runs a few milliseconds past the expected time but often a day too late (2, 4, 7, 10 at around 1 PM).
If can almost only be in my Task.Delay calculation, but I don't know why.
I have other services running with different starts/delays but with the same problem.
Can anyone see what's wrong? I'm open for other approaches but I prefer not to use libraries like Hangfire.
Upvotes: 1
Views: 1843
Reputation: 46249
You might look for a scheduler quartz, which is very suitable to use the crontab format that is very suitable for the background scheduler.
If you want to find a light way crontab library Cronos or NCrontab that can only get the time by crontab.
For all Of them, I would prefer using Cronos
library because that supports UTC and daylight saving time transitions.
public class ReminderService : BackgroundService
{
private const string cronExpression= "0 13 1,3,6,9 * *";
private readonly CronExpression _cronJob;
public ReminderService()
{
_cronJob = CronExpression.Parse(cronExpression);
}
protected override async Task ExecuteAsync(CancellationToken stopToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var now = DateTime.UtcNow;
var nextUtc = _cronJob.GetNextOccurrence(now);
await Task.Delay(now - nextUtc.Value, stoppingToken);
await DoWork();
}
}
protected async Task DoWork()
{
// The work...
}
}
Here is a very awesome website cron-expression-generator helps us get crontab expression by UI
Upvotes: 3