与作业一样,触发器相对容易使用,但是在您可以充分利用Quartz.NET之前,确实需要了解和理解各种可自定义的选项。 此外,如前所述,您可以选择不同类型的触发器来满足不同的调度需求。
1、常见触发器属性(Common Trigger Attributes)
除了所有触发器类型都具有用于跟踪其身份的TriggerKey属性之外,还有许多其他属性对所有触发器类型都是通用的。 在构建触发器定义时,使用TriggerBuilder设置这些常用属性(后面将举例说明)。
以下是所有触发器类型共有的属性列表:
1)、JobKey 属性指示触发器触发时应该执行作业的标识。
2)、StartTimeUtc 属性指示触发器的计划首次生效是什么时候。该值是DateTimeOffset对象,用于定义给定日历日期的时刻。对于某些触发器类型,触发器实际上会在开始时触发,对于其他触发器类型,它只是标记应该开始遵循调度的时间。这意味着您可以存储一个触发器,其中包含一个计划,例如1月份的“每月的第5天”,如果StartTimeUtc属性设置为4月1日,则会在第一次触发前几个月。
3)、EndTimeUtc 属性指示触发器的调度计划何时不再有效。换句话说,具有“每月的第5天”和7月1日结束时间表的触发器将在6月5日的最后一次触发后将结束。
其他的属性需要更多时间来解释,将在以下小节中讨论。
2、优先级
有时,当您有许多触发器(或Quartz.NET线程池中的工作线程比较少)时,Quartz.NET可能没有足够的资源来立即触发计划中该同时触发的所有触发器。 在这种情况下,您可能希望控制哪些触发器在可用的Quartz.NET工作线程中首先触发。为此,您可以在Trigger上设置priority属性。 如果同时触发N个触发器,但是当前只有Z个工作线程可用,则首先执行具有最高优先级的第一个Z触发器。如果未在触发器上设置优先级,则它将使用默认优先级5,优先级的值可以是任何整数值,包括正数或者负数。
注意:优先级仅在触发器具有相同的激活时间时才进行比较。定于10:59激活的触发器总是在定于11:00激活的触发器之前开火。
注意:当检测到触发器的作业需要恢复时,其恢复的调度优先级与原始触发器相同。
3、Misfire Instructions
触发器的另一个重要特性是它的“失火指令”。 如果持久性触发器由于调度程序被关闭而“错过”其触发时间,或者因为Quartz.NET的线程池中没有可用于执行作业的线程,则会发生失败。 不同的触发类型可以使用不同的失火指令。 默认情况下,它们使用“智能策略”指令 - 该指令具有基于触发类型和配置的动态行为。 当调度程序启动时,它会搜索任何已失效的持久触发器,然后根据各自配置的失火指令更新每个触发器。 当您在自己的项目中开始使用Quartz.NET时,您应该熟悉在给定触发器类型上定义的失火指令,并在其API文档中进行了解释。 有关失火指令的更多具体信息将在特定于每种触发类型的教程课程中给出。
4、Calendars
实现ICalendar接口的Quartz.NET Calendar对象可以在触发器存储在调度程序中时与触发器相关联。 日历可用于从触发器的触发计划中排除时间块。 例如,您可以创建一个触发器,在每个工作日上午9:30触发作业,但随后添加一个排除所有业务假期的日历。
Calendar可以是任何实现ICalendar接口的可序列化对象,如下所示:
1 namespace Quartz 2 { 3 public interface ICalendar 4 { 5 string Description { get; set; } 6 7 ICalendar CalendarBase { set; get; } 8 9 bool IsTimeIncluded(DateTimeOffset timeUtc); 10 11 DateTime GetNextIncludedTimeUtc(DateTimeOffset timeUtc); 12 13 ICalendar Clone(); 14 } 15 }
尽管日历对象可以“阻挡”只有一毫秒那么短的时间段,但很可能,你会对“封锁”整天的时间感兴趣。 为方便起见,Quartz.NET包含了类HolidayCalendar,它就是这样做的。
必须实例化日历对象,并通过AddCalendar(..)方法向调度程序注册日历对象。如果使用HolidayCalendar,则在实例化它之后,应该使用它的AddExcludedDate(DateTime日期)方法,可以将从调度中排除的天数做参数传递给该方法。同一个日历实例可以与多个触发器一起使用,例如:
1 HolidayCalendar cal = new HolidayCalendar(); 2 cal.AddExcludedDate(someDate); 3 4 await sched.AddCalendar("myHolidays", cal, false); 5 6 ITrigger t = TriggerBuilder.Create() 7 .WithIdentity("myTrigger") 8 .ForJob("myJob") 9 .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(9, 30)) // execute job daily at 9:30 10 .ModifiedByCalendar("myHolidays") // but not on holidays 11 .Build(); 12 13 // .. schedule job with trigger 14 15 ITrigger t2 = TriggerBuilder.Create() 16 .WithIdentity("myTrigger2") 17 .ForJob("myJob2") 18 .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(11, 30)) // execute job daily at 11:30 19 .ModifiedByCalendar("myHolidays") // but not on holidays 20 .Build(); 21 22 // .. schedule job with trigger2
触发器的构造/构建的细节将在接下来的几篇文章中给出。 现在,只要相信上面的代码创建了两个触发器,每个触发器计划每天触发。 但是,将跳过在日历排除的期间内发生的任何发射。
有关可能满足您需求的许多ICalendar实现,请参阅Quartz.Impl.Calendar命名空间。