Schedule jobs from Windows Service using Quartz — Part 4

This blog post is part of the series How to: Create Windows Service that schedules jobs, logs and is configurable by means of dependency injection.

In previous blog post, we’ve created a Windows Service using Topshelf, configured logging using log4net library and configured dependency injection using Autofac. In this blog post, we will schedule jobs from our service using Quartz library which is publicly available as a NuGet package.

Quartz is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems. It is a pure .NET library written in C# and is a port of very popular open source Java job scheduling framework. To learn more about great features that Quartz offers, visit https://www.quartz-scheduler.net/features.html.

We start by injecting IScheduler from Quartz namespace into our service.

We’ve also added two more methods — OnPause and OnContinue, to pause and resume our scheduled jobs.

IScheduler is the main interface of a Quartz Scheduler. ISchedulermaintains a registry of IJobDetails and ITriggers. Once registered, IScheduler is responsible for executing IJobs when their associated ITriggers fire (when their scheduled time arrives).

IScheduler instances are produced by a ISchedulerFactory. A scheduler that has already been created/initialized can be found and used through the same factory that produced it. After IScheduler has been created, it is in “stand-by” mode, and must have its IScheduler.Start(System.Threading.CancellationToken) method called before it will fire any IJob.

IJobs are to be created by the client program, by defining a class that implements IJob interface. IJobDetails are then created (also by the client) to define an individual instances of the IJobs. IJobDetail instances can then be registered with the IScheduler via the IScheduler.ScheduleJob(JobDetail, Trigger) or IScheduler.AddJob(JobDetail, bool) method.

ITriggers can then be defined to fire individual IJob instances based on given schedules. ISimpleTriggers are most useful for one-time firings, or firing at an exact moment in time, with N repeats with a given delay between them. ICronTriggers allow scheduling based on time of day, day of week, day of month, and month of year.

IJobs and ITriggers have name and group associated with them, which should uniquely identify them within a single IScheduler. The ‘group’ feature may be useful for creating logical groupings or categorizations of IJobs and ITriggers. If you don’t have need for assigning a group to a given IJobs of ITriggers, then you can use the SchedulerConstants.DefaultGroup constant defined on this interface.

Stored IJobs can also be ‘manually’ triggered using the IScheduler.TriggerJob(string, string) function.

Client programs may also be interested in the ‘listener’ interfaces that are available from Quartz. The IJobListener interface provides notifications of IJob executions. ITriggerListener interface provides notifications of ITrigger firings. ISchedulerListener interface provides notifications of IScheduler events and errors. Listeners can be associated with local schedulers through the IListenerManager interface.

The setup/configuration of a IScheduler instance is very customizable. You can learn more on official Quartz page online.

To resolve IScheduler, IJob and other types from Quartz namespace using Autofac, we would need to do some grunt work. Instead, we can use Autofac.Extras.Quartz NuGet package and register modules provided by that package in our container builder.

We can also provide configuration for Quartz, when registering modules, from app.config file

In app.config, we can define section ‘quartz’, or any other suitable name, and in that section provide configuration options that can be found in Quartz documentation.

We can now create custom job…

… and schedule it from our service in OnStart method

In our custom job, we’ve injected ILog to make sure everything is wired up properly with dependency injection — note that you need to configure IoC container to resolve ILog, which we haven’t done.

When we run our console application now, we get the following output:

On line that is third from the bottom, we can see Hi from MyJob log statement.

You can learn more about job scheduling with Quartz on https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/index.html.