Quartz.Extensions.DependencyInjection(opens new window) provides integration with Microsoft Dependency Injection(opens new window) .


Quartz 3.1 or later required.

# Installation

You need to add NuGet package reference to your project which uses Quartz.

Install-Package Quartz.Extensions.DependencyInjection

# Using

You can add Quartz configuration by invoking an extension method AddQuartz on IServiceCollection. The configuration building wraps various configuration properties with strongly-typed API. You can also configure properties using standard .NET Core appsettings.json inside configuration section Quartz.

Example appsettings.json

  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
  "Quartz": {
    "quartz.scheduler.instanceName": "Quartz ASP.NET Core Sample Scheduler"

# DI aware job factories

Quartz comes with two built-in alternatives for job factory which can be configured via either calling UseMicrosoftDependencyInjectionJobFactory or UseMicrosoftDependencyInjectionScopedJobFactory. The former doesn't utilize scopes and is a bit more lightweight but the latter is required if you want to consume scoped services like Entity Framework's DbContext.

Example Startup.ConfigureServices configuration

public void ConfigureServices(IServiceCollection services)
    // base configuration from appsettings.json
    services.AddQuartz(q =>
        // handy when part of cluster or you want to otherwise identify multiple schedulers
        q.SchedulerId = "Scheduler-Core";
        // we take this from appsettings.json, just show it's possible
        // q.SchedulerName = "Quartz ASP.NET Core Sample Scheduler";
        // we could leave DI configuration intact and then jobs need
        // to have public no-arg constructor
        // the MS DI is expected to produce transient job instances
        // this WONT'T work with scoped services like EF Core's DbContext
        q.UseMicrosoftDependencyInjectionJobFactory(options =>
            // if we don't have the job in DI, allow fallback 
			// to configure via default constructor
            options.AllowDefaultConstructor = true;

        // or for scoped service support like EF Core DbContext
        // q.UseMicrosoftDependencyInjectionScopedJobFactory();
        // these are the defaults
        q.UseDefaultThreadPool(tp =>
            tp.MaxConcurrency = 10;

        // quickest way to create a job with single trigger is to use ScheduleJob
        // (requires version 3.2)
        q.ScheduleJob<ExampleJob>(trigger => trigger
            .WithIdentity("Combined Configuration Trigger")
            .WithDailyTimeIntervalSchedule(x => x.WithInterval(10, IntervalUnit.Second))
            .WithDescription("my awesome trigger configured for a job with single call")

        // you can also configure individual jobs and triggers with code
        // this allows you to associated multiple triggers with same job
        // (if you want to have different job data map per trigger for example)
        q.AddJob<ExampleJob>(j => j
            .StoreDurably() // we need to store durably if no trigger is associated
            .WithDescription("my awesome job")

        // here's a known job for triggers
        var jobKey = new JobKey("awesome job", "awesome group");
        q.AddJob<ExampleJob>(jobKey, j => j
            .WithDescription("my awesome job")

        q.AddTrigger(t => t
            .WithIdentity("Simple Trigger")    
            .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever())
            .WithDescription("my awesome simple trigger")

        q.AddTrigger(t => t
            .WithIdentity("Cron Trigger")    
            .WithCronSchedule("0/3 * * * * ?")
            .WithDescription("my awesome cron trigger")

        // you can add calendars too (requires version 3.2)
        const string calendarName = "myHolidayCalendar";
            name: calendarName,
            replace: true,
            updateTriggers: true,
            x => x.AddExcludedDate(new DateTime(2020, 5, 15))

        q.AddTrigger(t => t
            .WithIdentity("Daily Trigger")
            .WithDailyTimeIntervalSchedule(x => x.WithInterval(10, IntervalUnit.Second))
            .WithDescription("my awesome daily time interval trigger")
        // also add XML configuration and poll it for changes
        q.UseXmlSchedulingConfiguration(x =>
            x.Files = new[] { "~/quartz_jobs.config" };
            x.ScanInterval = TimeSpan.FromSeconds(2);
            x.FailOnFileNotFound = true;
            x.FailOnSchedulingError = true;

        // convert time zones using converter that can handle Windows/Linux differences
        // add some listeners

        // example of persistent job store using JSON serializer as an example
        q.UsePersistentStore(s =>
            s.UseProperties = true;
            s.RetryInterval = TimeSpan.FromSeconds(15);
            s.UseSqlServer(sqlServer =>
                sqlServer.ConnectionString = "some connection string";
                // this is the default
                sqlServer.TablePrefix = "QRTZ_";
            s.UseClustering(c =>
                c.CheckinMisfireThreshold = TimeSpan.FromSeconds(20);
                c.CheckinInterval = TimeSpan.FromSeconds(10);
	// we can use options pattern to support hooking your own configuration
	// because we don't use service registration api, 
	// we need to manually ensure the job is present in DI
		.Configure<IOptions<SampleOptions>>((options, dep) =>
			if (!string.IsNullOrWhiteSpace(dep.Value.CronSchedule))
				var jobKey = new JobKey("options-custom-job", "custom");
				options.AddJob<ExampleJob>(j => j.WithIdentity(jobKey));
				options.AddTrigger(trigger => trigger
					.WithIdentity("options-custom-trigger", "custom")