Quartz.NET - 教程 4: 更多关于触发器

译者注: 目录在这 [译]Quartz.NET 3.x 教程
译者注: 原文在这 Lesson 4: More About Triggers

跟作业一样, 触发器也相当容易使用, 但确实包含各种可定制的选项, 在充分利用 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个触发器同时触发, 但当前只有Z个工作线程可用, 则首先执行具有最高优先级的Z个触发器. 如果你没有在触发器上设置优先级, 那么它将使用默认优先级5. 优先级的值可以设置为任意整数, 可以是正数或负数.

注意: 仅当触发器具有相同的触发时间时才比较优先级. 计划在10:59执行的触发器始终在11:00执行的触发器的前触发.

注意: 当检测到触发器的作业需要恢复时, 其调度恢复的优先级与原始触发器相同.

哑火说明

触发器的另一个重要属性是其 "Misfire Instructions". 如果由于调度程序关闭而导致持续触发器 "遗漏" 其触发时间, 或者 Quartz.NET 线程池中没有可用的线程来执行作业, 则会发生哑火. 不同的触发类型可以使用不同的哑火指令. 默认情况下, 他们使用 "智能策略" 指令 - 它具有基于触发类型和配置的动态行为. 当调度程序启动时, 她会搜索任何发生故障的持久化的触发器, 然后根据各自配置的哑火指令更新其中的每个触发器. 当你在自己的项目中开始使用 Quartz.NET 时, 你应该让自己熟悉在给定触发器类型上定义的哑火指令, 并在他们的 API 文档中解释. 关于哑火指令的更多具体信息将在针对每种触发类型的教程课程中给出.

日历

实现了 ICalendar 接口的 Quartz. NET Calendar 对象可以在触发器存储在调度程序中时与触发器关联. 日历对于从触发器的调度时间表中排除时间块非常有用. 例如, 你可以创建一个触发器, 并在每个工作日的上午9:30触发一个作业, 随后再添加日历排除所有的业务假期.

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

namespace Quartz
{
    public interface ICalendar
    {
	string Description { get; set; }

	ICalendar CalendarBase { set; get; }

	bool IsTimeIncluded(DateTimeOffset timeUtc);

	DateTime GetNextIncludedTimeUtc(DateTimeOffset timeUtc);

	ICalendar Clone();
    }
}

即使日历可以 "屏蔽" 一毫秒那么短的时间段, 但最有可能的是, 你会对 "屏蔽" 一整天更感兴趣. 为了方便起见, Quartz.NET 内置了类 HolidayCalendar, 她就是这么做的.

日历必须实例化并通过 AddCalendar(..) 方法注册到调度程序中. 如果你使用 HolidayCalendar, 那么在实例化之后, 你应该使用她的 AddExcludedDate(DateTime date) 方法来添加你希望排除在日程之外的日子. 同一日历实例可以用于多个触发器, 例如:

举个栗子

HolidayCalendar cal = new HolidayCalendar();
cal.AddExcludedDate(someDate);
    
await sched.AddCalendar("myHolidays", cal, false);
    
Trigger t = TriggerBuilder.Create()
    .WithIdentity("myTrigger")
    .ForJob("myJob")
    .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(9, 30)) // 每天 9:30 执行作业
    .ModifiedByCalendar("myHolidays") // 指定节假日不执行
    .Build();

// .. schedule job with trigger

ITrigger t2 = TriggerBuilder.Create()
    .WithIdentity("myTrigger2")
    .ForJob("myJob2")
    .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(11, 30)) // 每天 11:30 执行作业
    .ModifiedByCalendar("myHolidays") // 指定节假日不执行
    .Build();
    
// .. schedule job with trigger2 

触发器的构造/构建细节将在接下来的几节课程中给出. 现在, 只需要相信上面的代码创建了两个触发器, 每天触发一次调度. 另外, 在排除的日历期间内发生的任何触发都将被跳过.

请参阅 Quartz.Impl.Calendar 命名空间来获取更多可以适合你需求的 ICalendar 实现.

posted @ 2020-02-24 10:37  taadis  阅读(...)  评论(...编辑  收藏