Cron-like scheduling with .NET background workers
For many systems, bringing in a full scheduler (Quartz, Hangfire, etc.) is overkill.
A simple recurring job runner based on BackgroundService can be enough.
1. Represent schedules in code
I usually start with something simple like “run every N minutes” or “run at a specific hour”, implemented with an interface such as:
public interface IRecurringJob
{
string Name { get; }
TimeSpan Interval { get; }
Task ExecuteAsync(CancellationToken token);
}
The background service then loops over registered jobs and checks if each is due.
2. Avoid drift
If you just await Task.Delay(job.Interval) after each run,
execution can drift over time. Instead, record the planned next run and
calculate delays based on that.
3. Isolate slow or failing jobs
One slow job shouldn’t block all others. Options:
- Run each job in its own task with a timeout.
- Use a small degree-of-parallelism for job execution.
- Log failures per job, not per scheduler loop.