Quartz.NET是一个功能齐全的开源作业调度系统,(Quartz读音:[kwɔːts],发音类似中文“扩儿词”),从最小的应用程序到大型企业系统都可以使用。Quartz.NET是一个用C#编写的纯.NET库,是非常流行的开源Java作业调度框架Quartz的一个对等功能的实现。其简单的使用方式这里做一下介绍。网上比比皆是,依旧自己在纪录一遍的意义在于:加深记忆和理解,方便重用和查找。
基本结构
首先咱们先看一下quartz的整体结构,如图:

每一个作业(任务/工作)都有一个作业调度器进行管理,作业调度器的启动需要三个条件:1基础信息(数据信息,执行程序),2、触发条件。
入门使用
1、咱们在使用的时候,首先需要创建一个作业调度池:
ISchedulerFactory schedf = new StdSchedulerFactory();//工厂
IScheduler sched =await schedf.GetScheduler();//作业调度器
sched.Start();//启动,开始调度
2、为了方便后面的代码,咱们先创建一个执行程序:
[DisallowConcurrentExecutionAttribute]
public class HelloJob : IJob
{
public Task Execute(IJobExecutionContext context)
{
//读取传递的数据
context.JobDetail.JobDataMap.GetString("这是ke");
Console.WriteLine(context.RefireCount);
Console.WriteLine("Info From HelloJob:" + DateTime.Now.ToString());
return Task.FromResult(0);
}
}
3、创建基础数据,指定执行的代码和传递的数据
IJobDetail job = JobBuilder.Create<HelloJob>().UsingJobData("这是key","value").Build();
4、触发器(就是执行策略)有4类,下面通过创建一个简单的触发器,来分别说一下这几类触发器:
a、一般简单的触发策略可以如下写:
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInSeconds(3).WithRepeatCount(9)).Build();
含义是:三秒执行一次,一直到执行次数计数器值为9,当第一次执行,执行的计数器等于0),总共执行10次。
b、简单的触发策略如果不设置job启动时间点,默认都是按照程序启动时间开始计算的,下面创建一个在10秒后才开始的触发策略:
ISimpleTrigger trigger = (ISimpleTrigger)((TriggerBuilder.Create().StartAt(DateTimeOffset.Now.AddSeconds(10))).WithSimpleSchedule(x =>x.WithIntervalInSeconds(1).WithRepeatCount(2)).Build());
含义是:从当前时间算起,10秒后启动,一秒一次,执行三次(执行的计数器数=2),当然也可以使用EndAt()设置结束时间
注:其实这种一直“.”的写法,我不喜欢,可读性太差了。
c、使用自定义表达式定义执行策略,网上有表达式生成工具:http://cron.qqe2.com/
//定义执行策略
var _mySchedule = CronScheduleBuilder.CronSchedule("0/5 0 14,18 * * ? *");
//构建触发器
ICronTrigger _myTrigger = (ICronTrigger)(TriggerBuilder.Create().WithIdentity("名字", "组名").WithSchedule(_mySchedule).Build());
d、其他的触发器策略类型:CalendarIntervalTriggerImpl和DailyTimeIntervalTriggerImpl,具体如何使用建议查看文档。
5、加入到作业调度器中,此时因为作业调度已经启动,所以,任务就已经被安排下去了。就是待执行的了,咱们就不用管了,由作业调度器进行安排什么时候执行如何执行等等
sched.ScheduleJob(job, trigger);
Misfire策略
misfire,英[ˌmɪsˈfaɪə(r)],不奏效,不起火。在作业调度中的作用就是,如果作业线程“不奏效”,咱们可以使用对应办法就行处理。
1、先说CronTrigger的
withMisfireHandlingInstructionFireAndProceed(默认)
以当前时间为触发频率立刻触发一次执行,然后按照Cron频率依次执行
withMisfireHandlingInstructionIgnoreMisfires
a、以错过的第一个频率时间立刻开始执行
b、重做错过的所有频率周期后
c、当下一次触发频率发生时间大于当前时间后,再按照正常的Cron频率依次执行
withMisfireHandlingInstructionDoNothing
a、不触发立即执行
b、等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
2、SimpleTrigger的
withMisfireHandlingInstructionFireNow
a、以当前时间为触发频率立即触发执行
b、执行至FinalTIme的剩余周期次数
c、以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
d、调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
withMisfireHandlingInstructionIgnoreMisfires
a、以错过的第一个频率时间立刻开始执行
b、重做错过的所有频率周期
c、当下一次触发频率发生时间大于当前时间以后,按照Interval的依次执行剩下的频率
d、共执行RepeatCount+1次
withMisfireHandlingInstructionNextWithExistingCount
a、不触发立即执行
b、等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
c、以startTime为基准计算周期频率,并得到FinalTime
d、即使中间出现pause,resume以后保持FinalTime时间不变
withMisfireHandlingInstructionNextWithRemainingCount
a、不触发立即执行
b、等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
c、以startTime为基准计算周期频率,并得到FinalTime
d、即使中间出现pause,resume以后保持FinalTime时间不变
withMisfireHandlingInstructionNowWithExistingCount(默认)
a、以当前时间为触发频率立即触发执行
b、执行至FinalTIme的剩余周期次数
c、以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
d、调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
withMisfireHandlingInstructionNowWithRemainingCount
a、以当前时间为触发频率立即触发执行
b、执行至FinalTIme的剩余周期次数
c、以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
d、调整后的FinalTime会略大于根据starttime计算的到的FinalTime值
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
a、此指令导致trigger忘记原始设置的starttime和repeat-count
b、触发器的repeat-count将被设置为剩余的次数
c、这样会导致后面无法获得原始设定的starttime和repeat-count值