QuartzNet is a port of the popular Java library to C# that allows for durable background scheduling of jobs with a sophisticated triggering system ranging from immediate to repeatable options.  There are other options in the .NET world such as HangFire, QuartzNet is less flashy and commercial, but it has been rock solid and works over a variety of issues.  Note that using generics for job definitions/triggers can cause issues with serialization etc so be careful.

Key points

  • Fail over capability and ability to restart failed job automatically
  • Load balancing in a clustered manner to distribute the work across application servers/containers
  • Built off a background thread pool that can be adjusted as needed or configured locally to match production deployment
  • Persistence as serialized data to choice of durable storage

Setup can be as easy as this

var factory = new StdSchedulerFactory({ {"quartz.threadPool.threadCount", "2"} });
var scheduler = await factory.GetScheduler();
await scheduler.Start();

Define a job TodoJob that inherits from IJob and implements the Execute method

public class TodoJob : IJob
{
	public async Task Execute(IJobExecutionContext context)
	{
		await ...
	}
}

Now to create a job of this type and trigger it to run forever every hour

var job = JobBuilder.Create<TodoJob>()
	.WithIdentity(keys.Job, "group")
	.Build();
var trigger = TriggerBuilder.Create()
	.WithIdentity(keys.Trigger, "group")
	.StartAt(DateBuilder.EvenHourDateAfterNow())
	.WithSimpleSchedule(x => x.WithIntervalInHours(1).RepeatForever())
	.Build();
var scheduled = await scheduler.ScheduleJob(job, trigger);