SoFunction
Updated on 2025-03-07

Detailed explanation of the task and trigger implementation method

Quartz API

The main interfaces and classes of the Quartz API are as follows:

  • IScheduler - The main API for interacting with schedulers
  • IJob - The scheduler will execute an instance that implements this interface
  • IJobDetail - An instance used to define a task
  • ITrigger - Components that define task execution schedules
  • JobBuilder - Used to define/construct an instance of JobDetail, where the instance of JobDetail defines an instance of Jobs
  • TriggerBuilder - An instance used to define/construct Trigger

In this article, for readability, the following statements are interchangeable: IScheduler and Scheduler, IJob and Job, IJobDetail and JobDetail, ITrigger and

Trigger.

The life cycle of a scheduler starts with the creation of the SchedulerFactory to the end of the Shutdown() method that calls it. After an IScheduler is implemented, you can use add, delete, list tasks and triggers, or other schedule-related operations (such as pausing a trigger). However, as mentioned in Lesson 1, a scheduler does not really trigger a task trigger (execute a task) until the Start() method is called to start it.

Quartz provides a "builder" class defined as a domain-specific language (DSL, sometimes called a "fluent interface". In the previous lesson, you saw an example of it, and here we look at some of it.

	// define the job and tie it to our HelloJob class
	IJobDetail job = <HelloJob>()
		.WithIdentity("myJob", "group1") // name "myJob", group "group1"
		.Build();
		
	// Trigger the job to run now, and then every 40 seconds
	ITrigger trigger = ()
		.WithIdentity("myTrigger", "group1")
		.StartNow()
		.WithSimpleSchedule(x => x
			.WithIntervalInSeconds(40)
			.RepeatForever())      
		.Build();
		
	// Tell quartz to schedule the job using our trigger
	await (job, trigger);

In this code, when using JobBuilder to define a job, a stream interface is used to build an IJobDetail. Similarly, when defining triggers using TriggerBuilder, stream interfaces and extension methods that return trigger types are used. The available scheduling extension methods are:

  • WithCalendarIntervalSchedule
  • WithCronSchedule
  • WithDailyTimeIntervalSchedule
  • WithSimpleSchedule

The DateBuilder class provides several ways to construct a DateTimeOffset instance to specify a specific point in time (for example, specifying the time of the next hour - in other words, if it is 9:43:27 now, the specified time is 10:00:00).

Jobs and Triggers

Task is a class that implements the IJob interface, and it has only one simple method.

IJob Interface

  namespace Quartz
  {
    public interface IJob
    {
      Task Execute(JobExecutionContext context);
    }
  }

When a task's trigger is triggered, one of the scheduler's worker threads will call the Execute(..) method. The JobExecutionContext object passed to this method provides a job instance containing its "run-time" environment information, including the handle to the scheduler that executes it, the handle to the trigger that triggers the operation, the JobDetail object of the task, and some other information.

The JobDetail object is generated when the client (your program) adds a task to the scheduler. It includes a variety of Job properties and provides a JobDataMap, which can store state information for instances of the job class. This is the essence of the job instance, which will be introduced in more detail in the next section.

Trigger object is used to trigger the execution of a task. When you want to schedule a task, you should instantiate a trigger and "adjust" its properties to meet the schedule you want. The trigger can also have a JobDataMap object associated with it, which is very useful for passing parameters to tasks. Quartz provides several different types of triggers, but the most commonly used ones are SimpleTrigger (ISimpleTrigger interface) and CronTrigger (ICronTrigger interface).

SimpleTrigger is very convenient if you need to "one-time" operations (only once at a specified time), or do a task at a specified time and perform N times in a delay time. If you trigger tasks based on calendar-like plans, such as "Friday, Noon" or "10:15 on the 10th of the month", then CronTrigger is very useful.

Why use tasks and triggers separately? Many task schedulers do not have the concept of separate tasks and triggers. Some of them simply define a "task" as an execution time (plan) with simple task identifiers, while others are much like the concept of Quartz's tasks and triggers combined. When developing Quartz, it made great sense to decide that we separated the plan from the work that was done in the plan. There are many benefits (we think).

For example, a task may be created and stored in a task schedule independent of a trigger, and multiple triggers may be associated with the same task. Another low coupling benefit is that you can configure tasks that have expired but are still in the scheduler, which allows you to schedule it again without redefinition. This also allows you to modify or replace a trigger without redefining the task associated with it.

Identities

Tasks and triggers can give identification keys when registered with the Quartz scheduler. JobKey and TriggerKey make them grouped, making it easy to classify and plan your tasks and triggers, such as "Report Tasks" and "Maintenance Tasks". The name attributes of tasks and triggers within the same group must be unique. In other words, the complete key (identification) of the task and the trigger, that is, the combination of name and group is unique.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.