Quartz.NETQuartz.NET
Home
Features
Blog
Discussions
NuGet
GitHub
Home
Features
Blog
Discussions
NuGet
GitHub
  • Getting Started

    • Overview
    • Quartz 4 Quick Start
    • Tutorial
      • Using Quartz
      • Jobs And Triggers
      • More About Jobs & JobDetails
      • Job Data
      • More About Triggers
      • Querying Jobs and Triggers
      • Simple Triggers
      • Cron Triggers
      • RecurrenceTrigger
      • Time and TimeProvider
      • Trigger and Job Listeners
      • Scheduler Listeners
      • Job Execution Middleware
      • Job Stores
      • Configuration, Resource Usage and Building a Scheduler
      • Building a Scheduler Without a Host
      • Clustering
      • Execution Groups
      • Node Affinity (Preferred Node)
      • Testing
      • Compile-Time Checks
      • Declaring Jobs with Attributes
      • Delegate Jobs
    • Configuration Reference
    • JSON Configuration
    • Cron Expression Reference
    • Multi-Tenancy
    • Comparison
    • Frequently Asked Questions
    • Best Practices
    • Before You Go Live
    • Operating a Cluster
    • Log Events
    • Tenancy Patterns
    • Database Schema
    • Database Schema Changes
    • Migration Guide
    • Troubleshooting
    • API Documentation
  • How To's
    • One-Off Job
    • Rescheduling Jobs
    • Backfill
    • Retrying Failed Jobs
    • Pausing with a Reason
    • Job Continuations
    • Overlap Policy
    • Progress and Execution Logs
    • Job Outcomes
    • Multiple Triggers
    • Job Template
    • Running Quartz under Aspire
    • Quartz.NET with Wolverine
    • Coming from Hangfire
    • Coming from TickerQ
    • Embedding Quartz in a Library
    • Running under an External Leader Election
    • Publishing Trimmed and Native AOT
    • Extending Quartz: what is open, what is closed, and how to ask
    • A Job Store of Your Own
    • A Driver Delegate for a New Database
    • Persisting a Custom Trigger Type
    • A Lock Handler of Your Own
  • Packages

    • Quartz Core Additions

      • Jobs
      • Serialization (System.Text.Json)
      • JSON Serialization
      • Plugins
    • Integrations

      • Aspire Integration
      • ASP.NET Core Integration
      • HTTP API
      • HTTP Client
      • Dashboard
      • Hosted Services Integration
      • Microsoft DI Integration
      • Multiple Schedulers with Microsoft DI
      • Observability
      • Redis Lock Handler
      • TimeZoneConverter Integration
      • Weasel Schema Management
    • 3rd Party Plugins for Quartz
  • Quartz 3.x

    • Getting Started

      • Quartz 3 Quick Start
      • Tutorial
        • Using Quartz
        • Library Overview
        • Jobs And Triggers
        • More About Jobs
        • More About Triggers
        • Execution Groups
        • Node Affinity (Preferred Node)
        • Simple Triggers
        • Cron Triggers
        • RecurrenceTrigger
        • Trigger and Job Listeners
        • Scheduler Listeners
        • Job Stores
        • Tuning the Scheduler
        • Configuration, Resource Usage and SchedulerFactory
        • Advanced (Enterprise) Features
      • Configuration Reference
      • JSON Configuration
      • Multi-Tenancy
      • Frequently Asked Questions
      • Best Practices
      • Tenancy Patterns
      • Troubleshooting
      • API Documentation
      • Database Schema
      • Database Schema Changes
      • Migration Guide
      • Miscellaneous Features
    • How To's

      • One-Off Job
      • Multiple Triggers
      • Job Template
      • Using the CronTrigger
      • Rescheduling Jobs
    • Packages

      • Quartz Core Additions

        • Dashboard
        • Jobs
        • Serialization (System.Text.Json)
        • Serialization (Newtonsoft Json.NET)
        • Plugins
      • Integrations

        • ASP.NET Core Integration
        • Hosted Services Integration
        • Microsoft DI Integration
        • Multiple Schedulers with Microsoft DI
        • OpenTelemetry Integration
        • OpenTracing Integration
        • Redis Lock Handler
        • TimeZoneConverter Integration
      • 3rd Party Plugins for Quartz
  • Old Releases

    • Quartz 2.x
      • Quartz 2 Quick Start
      • Tutorial
        • Lesson 1: Using Quartz
        • Lesson 2: Jobs And Triggers
        • Lesson 3: More About Jobs & JobDetails
        • Lesson 4: More About Triggers
        • Lesson 5: SimpleTrigger
        • Lesson 6: CronTrigger
        • Lesson 7: TriggerListeners and JobListeners
        • Lesson 8: SchedulerListeners
        • Lesson 9: JobStores
        • Lesson 10: Configuration, Resource Usage and SchedulerFactory
        • Lesson 11: Advanced (Enterprise) Features
        • Lesson 12: Miscellaneous Features of Quartz
        • CronTrigger Tutorial
      • Configuration Reference
      • Migration Guide
      • API Documentation
    • Quartz 1.x
      • Tutorial
        • Lesson 1: Using Quartz
        • Lesson 2: Jobs And Triggers
        • Lesson 3: More About Jobs & JobDetails
        • Lesson 4: More About Triggers
        • Lesson 5: SimpleTrigger
        • Lesson 6: CronTrigger
        • Lesson 7: TriggerListeners and JobListeners
        • Lesson 8: SchedulerListeners
        • Lesson 9: JobStores
        • Lesson 10: Configuration, Resource Usage and SchedulerFactory
        • Lesson 11: Advanced (Enterprise) Features
        • Lesson 12: Miscellaneous Features of Quartz
      • API Documentation
  • License

The Quartz API

TypeRole
ISchedulerthe main API for interacting with the scheduler
IJobimplemented by the work the scheduler runs
IJobDetaildefines an instance of a job
ITriggerthe schedule a job runs on; a job can have several triggers
JobBuilderbuilds IJobDetail instances
TriggerBuilderbuilds ITrigger instances
QuartzSchedulerBuilderbuilds a scheduler when there is no host to register Quartz with

The tutorial uses IScheduler and Scheduler, IJob and Job, IJobDetail and JobDetail, and ITrigger and Trigger interchangeably.

A scheduler exists from the moment the container builds it until Shutdown(). Meanwhile IScheduler adds, removes and lists jobs and triggers and performs other operations such as pausing a trigger. Triggers do not fire until Start() is called; the hosted service calls it, as shown in Lesson 1.

Jobs and triggers are defined with fluent builders. The example from the previous lesson:

// define the job and tie it to our HelloJob class
IJobDetail job = JobBuilder.Create<HelloJob>()
    .WithIdentity("myJob", "group1") // name "myJob", group "group1"
    .Build();

// Trigger the job to run now, and then every 40 seconds
ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("myTrigger", "group1")
    .StartNow()
    .WithSimpleSchedule(x => x
        .WithInterval(TimeSpan.FromSeconds(40))
        .RepeatForever())
    .Build();

// Tell Quartz to schedule the job using our trigger
await scheduler.ScheduleJob(job, trigger);

JobBuilder builds the IJobDetail. TriggerBuilder builds the trigger, with one schedule method per trigger type:

MethodSchedule
WithSimpleSchedulea fixed interval, repeated a number of times or forever (SimpleTriggers)
WithCronSchedulea cron expression (CronTriggers); H tokens spread fire times across triggers
WithRecurrenceSchedulean RFC 5545 RRULE, for patterns cron cannot say, such as "the 2nd Monday of the month"
WithCalendarIntervalSchedulean interval in calendar units: "every month" keeps the day of the month, "every day" keeps the wall-clock hour across a daylight saving change
WithDailyTimeIntervalSchedulean interval inside a daily time window on chosen days of the week

A daily time interval schedule looks like StartingDailyAt(new TimeOnly(9, 0)), EndingDailyAt(new TimeOnly(17, 0)), OnMondayThroughFriday(). Times of day are TimeOnly in 4.0; 3.x had its own TimeOfDay type.

DateBuilder builds a DateTimeOffset that is awkward to write out: DateBuilder.Create().AtHourMinuteAndSecond(22, 0, 0).Build() is today at 22:00:00, and DateBuilder.CreateInTimeZone(timeZone) does the same in a given zone. When you pass the scheduler's TimeProvider, both read the clock through it, so a test that fakes time sees the faked time.

Jobs and Triggers

A job is a class that implements the IJob interface, which has only one simple method:

IJob Interface

namespace Quartz
{
    public interface IJob
    {
        ValueTask Execute(IJobExecutionContext context, CancellationToken cancellationToken = default);
    }
}

When the job's trigger fires, one of the scheduler's worker threads calls Execute. The IJobExecutionContext carries the run-time environment: the scheduler that ran the job, the trigger that fired it, the job's JobDetail, and a few other items.

cancellationToken is the same token as context.CancellationToken. It is a separate parameter so that analysis (CA2016) catches a job that does not forward it.

Your program creates the JobDetail when it adds the job to the scheduler. It holds the job's settings and a JobDataMap for state; the next lesson covers it.

A trigger fires a job. It can also carry a JobDataMap, for parameters specific to its firings. The common trigger types:

TriggerInterfaceUse for
SimpleTriggerISimpleTriggerone-shot execution at a moment, or a start time repeated N times with a delay of T between executions
CronTriggerICronTriggercalendar-like schedules: "every Friday, at noon", "at 10:15 on the 10th day of every month"
RecurrenceTriggerIRecurrenceTriggerRFC 5545 RRULE patterns cron cannot express: "every 2nd Monday of the month", "every other week on specific days", "the last weekday of March each year"

Jobs and triggers are separate so that:

  • a job can be stored without a trigger, and many triggers can fire the same job;
  • a job can stay in the scheduler after its triggers expire and be rescheduled later without being re-defined;
  • a trigger can be changed or replaced without re-defining its job.

Identities

Jobs and triggers are identified by keys (JobKey and TriggerKey), each a name plus a group. Groups organize jobs and triggers into categories such as "reporting jobs" and "maintenance jobs". A name must be unique within its group. A key given only a name is in the group Key<T>.DefaultGroup, "DEFAULT".

Next: Lesson 3: More About Jobs & JobDetails and Lesson 5: More About Triggers.

Help us by improving this page!
Last Updated: 10/6/26, 2:13 PM
Contributors: Marko Lahma, Claude Opus 5.5
Prev
Using Quartz
Next
More About Jobs & JobDetails