In my app I have a handful of BackgroundServices. The problem is, that they run on unscheduled times. Sometimes exactly a day too late, sometimes two days in a row even though it should only run once a week.
This is how one of the BackgroundServices looks like:
using Cronos;
namespace MyApp.HostedServices
{
public class MyFirstService : BackgroundService
{
private const string schedule = "0 1 0 ? * *";
private readonly CronExpression _cron;
public MyFirstService()
{
_cron = CronExpression.Parse(schedule, CronFormat.IncludeSeconds);
}
protected override async Task ExecuteAsync(CancellationToken stopToken)
{
while (!stopToken.IsCancellationRequested)
{
DateTime utcNow = DateTime.UtcNow;
DateTime? nextUtc = _cron.GetNextOccurrence(utcNow);
await Task.Delay(nextUtc.Value - utcNow, stopToken);
if (utcNow.Day == 1) await DoWork();
/*
DateTime now = DateTime.Now;
DateTime start = now.Date.AddMinutes(1);
if (now > start) start = start.AddDays(1);
await Task.Delay(start.Subtract(now), stopToken);
if (now.Day == 1) await DoWork();
*/
}
}
protected async Task DoWork()
{
// The work to be done
}
}
}
Another example:
using Cronos;
namespace MyApp.HostedServices
{
public class MySecondService : BackgroundService
{
private const string schedule = "0 0 13 ? * *";
private readonly CronExpression _cron;
private readonly int[] reminderDays = { 1, 3, 6, 9 };
public MySecondService()
{
_cron = CronExpression.Parse(schedule, CronFormat.IncludeSeconds);
}
protected override async Task ExecuteAsync(CancellationToken stopToken)
{
while (!stopToken.IsCancellationRequested)
{
DateTime utcNow = DateTime.UtcNow;
DateTime? nextUtc = _cron.GetNextOccurrence(utcNow);
await Task.Delay(nextUtc.Value - utcNow, stopToken);
if (reminderDays.Contains(utcNow.Day)) await DoWork();
/*
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 to be done
}
}
}
I've asked the same question before and was adviced to use cron to calculate the next run instead of doing it myself. At first I thought that did it, but the problem persists.
For example did the MySecondService run both the sixth and seventh this month.
What could be wrong?