与作业一样,触发器也相对容易使用,但确实包含各种可自定义的选项,在充分利用 Quartz.NET 之前,您需要了解和理解这些选项。 此外,如前所述,您可以选择不同类型的触发器来满足不同的调度需求。

常见的触发器属性

除了所有触发器类型都具有用于跟踪其身份的 TriggerKey 属性之外,还有许多其他属性对所有触发器类型都是通用的。在构建触发器定义时,这些通用属性是使用 TriggerBuilder 设置的(示例如下)。

以下是所有触发器类型共有的属性列表:

  • JobKey 属性指示触发器触发时应执行的作业的标识。
  • StartTimeUtc 属性指示触发器的计划何时首次生效。该值是一个 DateTimeOffset 对象,用于定义给定日历日期的某个时刻。对于某些触发器类型,触发器实际上会在开始时间触发,而对于其他触发器类型,它只是标记应该开始遵循计划的时间。这意味着您可以在 1 月期间使用诸如“每月第 5 天”之类的计划存储触发器,并且如果 StartTimeUtc 属性设置为 4 月 1 日,则它将在第一次触发前几个月。
  • EndTimeUtc 属性指示触发器的计划何时不再有效。换句话说,计划为“每月第 5 天”且结束时间为 7 月 1 日的触发器将在 6 月 5 日最后一次触发。

其他需要更多解释的属性将在以下小节中讨论。

优先级

有时,当您有许多触发器(或 Quartz.NET 线程池中的工作线程很少)时,Quartz.NET 可能没有足够的资源来立即触发所有计划同时触发的触发器。在这种情况下,您可能希望控制哪些触发器首先破解可用的 Quartz.NET 工作线程。为此,您可以在触发器上设置优先级属性。如果要同时触发 N 个 Trigger,但当前只有 Z 个工作线程可用,则首先执行优先级最高的前 Z 个 Trigger。如果您没有在触发器上设置优先级,那么它将使用默认优先级 5。优先级允许使用任何整数值,正数或负数。数字越大表示优先级越高。即优先级为 7 的触发器的优先级高于值为 5 的触发器。

提示

仅当触发器具有相同的触发时间时才比较优先级。计划在 10:59 触发的触发器总是会在计划在 11:00 触发的触发器之前触发。

提示

当检测到触发器的作业需要恢复时,它的恢复将按照与原始触发器相同的优先级进行调度。

失火指令

触发器的另一个重要属性是它的“失火指令”。 如果由于调度程序被关闭,或者因为 Quartz.NET 的线程池中没有可用的线程来执行作业,持久触发器“错过”其触发时间,则会发生不触发。 不同的触发器类型有不同的失火指令可供它们使用。 默认情况下,他们使用“智能策略”指令——该指令具有基于触发器类型和配置的动态行为。 当调度程序启动时,它会搜索任何未触发的持久触发器,然后根据其单独配置的不触发指令更新每个触发器。 当您开始在自己的项目中使用 Quartz.NET 时,您应该熟悉在给定触发器类型上定义的失火指令,并在其 API 文档中进行解释。 有关失火指令的更多具体信息将在针对每种触发器类型的教程课程中提供。

日历

实现 ICalendar 接口的 Quartz.NET 日历对象可以在触发器存储在调度程序中时与触发器相关联。 日历对于从触发器的触发时间表中排除时间块很有用。 例如,您可以创建一个触发器,在每个工作日的上午 9:30 触发一个工作,然后添加一个排除所有企业节假日的日历。

日历可以是任何实现 ICalendar 接口的可序列化对象,如下所示:

  1. namespace Quartz
  2. {
  3. public interface ICalendar
  4. {
  5. string Description { get; set; }
  6. ICalendar CalendarBase { set; get; }
  7. bool IsTimeIncluded(DateTimeOffset timeUtc);
  8. DateTime GetNextIncludedTimeUtc(DateTimeOffset timeUtc);
  9. ICalendar Clone();
  10. }
  11. }

尽管日历可以“屏蔽”小至毫秒的时间段,但您很可能会对“屏蔽”一整天的时间感兴趣。 为方便起见,Quartz.NET 包含了HolidayCalendar 类,它就是这样做的。

日历必须通过 AddCalendar(..) 方法实例化并注册到调度程序。 如果您使用 HolidayCalendar,在实例化它之后,您应该使用它的 AddExcludedDate(DateTime date) 方法来填充您希望从计划中排除的日期。 同一个日历实例可以与多个触发器一起使用,例如:

日历示例

  1. HolidayCalendar cal = new HolidayCalendar();
  2. cal.AddExcludedDate(someDate);
  3. await sched.AddCalendar("myHolidays", cal, false);
  4. ITrigger t = TriggerBuilder.Create()
  5. .WithIdentity("myTrigger")
  6. .ForJob("myJob")
  7. .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(9, 30)) // execute job daily at 9:30
  8. .ModifiedByCalendar("myHolidays") // but not on holidays
  9. .Build();
  10. // .. schedule job with trigger
  11. ITrigger t2 = TriggerBuilder.Create()
  12. .WithIdentity("myTrigger2")
  13. .ForJob("myJob2")
  14. .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(11, 30)) // execute job daily at 11:30
  15. .ModifiedByCalendar("myHolidays") // but not on holidays
  16. .Build();
  17. // .. schedule job with trigger2

触发器的构建/构建的细节将在接下来的几节课中给出。 现在,只要相信上面的代码创建了两个触发器,每个触发器都计划每天触发。 但是,将跳过在日历排除期间发生的任何解雇。

请参阅 Quartz.Impl.Calendar 命名空间,了解一些可能适合您需要的 ICalendar 实现。