Job Tracking using Quartz for .net

A project that I recently worked on has a worker role that runs about 40 jobs. With some of these jobs running for hours it became imperative that we knew when these jobs were running, if they were currently running, how long they were running, if they were overlapping with other dependent jobs etc.

Below I will show you how to easily setup Job Tracking using quartz-scheduler for .net.

Listeners provides us with the concept of Listeners. Listeners are objects that you create to perform actions based on events occurring within the scheduler. Quartz provides the following three listener interfaces:

  • ITriggerListener
  • IJobListener
  • ISchedulerListener

Each of these provides you with methods that get called on various events. More info on these can be found here and here.


First you need to create the implementation of whatever listener you want.

public class MyJobListener : IJobListener

Then you need to register the listener with your scheduler.

var scheduler = SchedulerFactory.GetScheduler();

All that is left is to implement the methods for the events you want to hook into.
You can register multiple listeners of the same type.


For my solution I hooked into the following methods
On IScheduleListener:

public void JobScheduled(ITrigger trigger)
    var name = trigger.JobKey.Name;
    DateTime? nextStartDate = null;
    if (trigger.GetNextFireTimeUtc().HasValue)
        nextStartDate = trigger.GetNextFireTimeUtc().Value.DateTime;
    //Do something with the information

This method gets called each time a job is scheduled. I use this so keep track of all the jobs that are scheduled and can easily extract which jobs have never ran. If you need to you can also extract the trigger type. You can then use the trigger type to form some kind of calendar view of when jobs will run.

On IJobListener:

public void JobToBeExecuted(IJobExecutionContext context)
    var name = context.JobDetail.JobType.Name;
    DateTime startTime = context.FireTimeUtc.HasValue ? context.FireTimeUtc.Value.DateTime : DateTime.UtcNow;
    //do something with info

public void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException)
    var name = context.JobDetail.JobType.Name;
    var runtime = context.JobRunTime;
    if(jobException != null)
        //do something with error info

    DateTime? nextRunDate = null;
        nextRunDate = context.NextFireTimeUtc.Value.DateTime;
    //do something with info

It is apparent that these methods get called just before a job executes and just after it finished. JobWasExecuted will get called even if there was an exception and quartz is nice enough to provide you with the exception object.

As mentioned we use the data gathered to make sure our worker role is in good health. There are various other methods on these interfaces so have a look at the linked documentation.

This post was first published on