Quartz.NET 是一个开源的做业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中。它提供了巨大的灵活性而不牺牲简单性。你可以用它来为执行一个做业而建立简单的或复杂的调度。它有不少特征,如:数据库支持,集群,插件,支持cron-like表达式等等。html
首先看一下简单的quartz_jobs.xml示例数据库
quartz_jobs.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- This file contains job definitions in schema version 2.0 format --> <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"> <processing-directives> <overwrite-existing-data>true</overwrite-existing-data> </processing-directives> <schedule> <job> <name>sampleJob</name> <group>sampleGroup</group> <description>Sample job for Quartz Server</description> <job-type>Quartz.Server.SampleJob, Quartz.Server</job-type> <durable>true</durable> <recover>false</recover> </job> <trigger> <simple> <name>sampleSimpleTrigger</name> <group>sampleSimpleGroup</group> <description>Simple trigger to simply fire sample job</description> <job-name>sampleJob</job-name> <job-group>sampleGroup</job-group> <misfire-instruction>SmartPolicy</misfire-instruction> <repeat-count>-1</repeat-count> <repeat-interval>10000</repeat-interval> </simple> </trigger> <job> <name>CommissionJob</name> <group>CommissionJob</group> <description>Sample job for Quartz Server</description> <job-type>Settlement.Jobs.CommissionJob, Settlement.Jobs</job-type> <durable>true</durable> <recover>false</recover> </job> <trigger> <cron> <name>sampleSimpleTrigger2</name> <group>sampleSimpleTrigger2</group> <job-name>sampleJob2</job-name> <job-group>sampleGroup2</job-group> <cron-expression>0/10 * * * * ?</cron-expression> </cron> </trigger> </schedule> </job-scheduling-data>
job-scheduling-data 为跟节点再也不解释express
processing-directives这个节点官方给的示例中就存在,干啥用的没有深刻了解,保持默认配置便可框架
schedule任务调度集合能够配置多个但貌似只有第一个的配置起做用,如何让多个schedule同时起做用但愿知道的童鞋告诉下,不胜感激。全部的job和trigger均放在这个节点下面asp.net
job 任务,其实就是1.x版本中的<job-detail>,这个节点是用来定义每一个具体的任务的,多个任务请建立多个job节点便可spa
- name(必填) 任务名称,同一个group中多个job的name不能相同,若未设置group则全部未设置group的job为同一个分组,如:<name>sampleJob</name>
- group(选填) 任务所属分组,用于标识任务所属分组,如:<group>sampleGroup</group>
- description(选填) 任务描述,用于描述任务具体内容,如:<description>Sample job for Quartz Server</description>
- job-type(必填) 任务类型,任务的具体类型及所属程序集,格式:实现了IJob接口的包含完整命名空间的类名,程序集名称,如:<job-type>Quartz.Server.SampleJob, Quartz.Server</job-type>
- durable(选填) 具体做用不知,官方示例中默认为true,如:<durable>true</durable>
- recover(选填) 具体做用不知,官方示例中默认为false,如:<recover>false</recover>
trigger 任务触发器,用于定义使用何种方式出发任务(job),同一个job能够定义多个trigger ,多个trigger 各自独立的执行调度,每一个trigger 中必须且只能定义一种触发器类型(calendar-interval、simple、cron).net
calendar-interval 一种触发器类型,使用较少,此处略过插件
simple 简单任务的触发器,能够调度用于重复执行的任务orm
- name(必填) 触发器名称,同一个分组中的名称必须不一样
- group(选填) 触发器组
- description(选填) 触发器描述
- job-name(必填) 要调度的任务名称,该job-name必须和对应job节点中的name彻底相同
- job-group(选填) 调度任务(job)所属分组,该值必须和job中的group彻底相同
- start-time(选填) 任务开始执行时间utc时间,北京时间须要+08:00,如:<start-time>2012-04-01T08:00:00+08:00</start-time>表示北京时间2012年4月1日上午8:00开始执行,注意服务启动或重启时都会检测此属性,若没有设置此属性或者start-time设置的时间比当前时间较早,则服务启动后会当即执行一次调度,若设置的时间比当前时间晚,服务会等到设置时间相同后才会第一次执行任务,通常若无特殊须要请不要设置此属性
- repeat-count(必填) 任务执行次数,如:<repeat-count>-1</repeat-count>表示无限次执行,<repeat-count>10</repeat-count>表示执行10次
- repeat-interval(必填) 任务触发间隔(毫秒),如:<repeat-interval>10000</repeat-interval> 每10秒执行一次
cron复杂任务触发器--使用cron表达式定制任务调度(强烈推荐)xml
- name(必填) 触发器名称,同一个分组中的名称必须不一样
- group(选填) 触发器组
- description(选填) 触发器描述
- job-name(必填) 要调度的任务名称,该job-name必须和对应job节点中的name彻底相同
- job-group(选填) 调度任务(job)所属分组,该值必须和job中的group彻底相同
- start-time(选填) 任务开始执行时间utc时间,北京时间须要+08:00,如:<start-time>2012-04-01T08:00:00+08:00</start-time>表示北京时间2012年4月1日上午8:00开始执行,注意服务启动或重启时都会检测此属性,若没有设置此属性,服务会根据cron-expression的设置执行任务调度;若start-time设置的时间比当前时间较早,则服务启动后会忽略掉cron-expression设置,当即执行一次调度,以后再根据cron-expression执行任务调度;若设置的时间比当前时间晚,则服务会在到达设置时间相同后才会应用cron-expression,根据规则执行任务调度,通常若无特殊须要请不要设置此属性
- cron-expression(必填) cron表达式,如:<cron-expression>0/10 * * * * ?</cron-expression>每10秒执行一次
了解了Quartz.NET 2.0的quartz_jobs.xml配置后就能够在项目中引用Quartz.dll文件而后实现IJob接口,根据实际项目中的须要灵活配置quartz_jobs,不须要再进行额外的开发,实现灵活的多任务调度,须要注意的是修改了quartz_jobs.xml文件后,quartz服务默认不会从新加载该文件,若要让修改后的文件生效须要重启下服务才行,另外start-time属性请必定慎用,若实在须要能够在使用完成后当即删除掉该属性不然可能形成很严重的后果(亲身经历血的教训,呵呵)
Quartz的cron表达式
按顺序依次为
秒(0~59)
分钟(0~59)
小时(0~23)
天(月)(0~31,可是你须要考虑你月的天数)
月(0~11)
天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
7.年份(1970-2099)
其中每一个元素能够是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符。因为"月份中的日期"和"星期中的日期"这两个元素互斥的,必需要对其中一个设置?.
0 0 10,14,16 * * ? 天天上午10点,下午2点,4点
0 0/30 9-17 * * ? 朝九晚五工做时间内每半小时
0 0 12 ? * WED 表示每一个星期三中午12点
有些子表达式能包含一些范围或列表
例如:子表达式(天(星期))能够为 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT”
“*”字符表明全部可能的值
所以,“*”在子表达式(月)里表示每月的含义,“*”在子表达式(天(星期))表示星期的每一天
“/”字符用来指定数值的增量
例如:在子表达式(分钟)里的“0/15”表示从第0分钟开始,每15分钟
在子表达式(分钟)里的“3/20”表示从第3分钟开始,每20分钟(它和“3,23,43”)的含义同样
“?”字符仅被用于天(月)和天(星期)两个子表达式,表示不指定值
当2个子表达式其中之一被指定了值之后,为了不冲突,须要将另外一个子表达式的值设为“?”
“L” 字符仅被用于天(月)和天(星期)两个子表达式,它是单词“last”的缩写
可是它在两个子表达式里的含义是不一样的。
在天(月)子表达式中,“L”表示一个月的最后一天
在天(星期)自表达式中,“L”表示一个星期的最后一天,也就是SAT
若是在“L”前有具体的内容,它就具备其余的含义了
例如:“6L”表示这个月的倒数第6天,“FRIL”表示这个月的最一个星期五
注意:在使用“L”参数时,不要指定列表或范围,由于这会致使问题
附:cronExpression配置说明
字段 容许值 容许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /
表达式 意义
"0 0 12 * * ?" 天天中午12点触发
"0 15 10 ? * *" 天天上午10:15触发
"0 15 10 * * ?" 天天上午10:15触发
"0 15 10 * * ? *" 天天上午10:15触发
"0 15 10 * * ? 2005" 2005年的天天上午10:15触发
"0 * 14 * * ?" 在天天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在天天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在天天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在天天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每一年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每个月15日上午10:15触发
"0 15 10 L * ?" 每个月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每个月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每个月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每个月的第三个星期五上午10:15触发
特殊字符 意义
* 表示全部值;
? 表示未说明的值,即不关心它为什么值;
- 表示一个指定的范围;
, 表示附加一个可能值;
/ 符号前表示开始时间,符号后表示每次递增的值;
L("last") ("last") "L" 用在day-of-month字段意思是 "这个月最后一天";用在 day-of-week字段, 它简单意思是 "7" or "SAT"。 若是在day-of-week字段里和数字联合使用,它的意思就是 "这个月的最后一个星期几" – 例如: "6L" means "这个月的最后一个星期五". 当咱们用“L”时,不指明一个列表值或者范围是很重要的,否则的话,咱们会获得一些意想不到的结果。
W("weekday") 只能用在day-of-month字段。用来描叙最接近指定天的工做日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个 月第15天的工做日”,即若是这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;若是这个月第15天是周日,那么触发器将会在这个月第 16天即周一触发;若是这个月第15天是周二,那么就在触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在 day-of-month指明一天,不能是一个范围或列表。也能够用“LW”来指定这个月的最后一个工做日。
# 只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用"6#3"指这个月第3个周五(6指周五,3指第3个)。若是指定的日期不存在,触发器就不会触发。
C 指和calendar联系后计算过的值。例:在day-of-month 字段用“5C”指在这个月第5天或以后包括calendar的第一天;在day-of-week字段用“1C”指在这周日或以后包括calendar的第一天。
Cron表达式被用来配置CronTrigger实例。Cron表达式是一个由7个子表达式组成的字符串。每一个子表达式都描述了一个单独的日程细节。这些子表达式用空格分隔,分别表示:
1. Seconds 秒
2. Minutes 分钟
3. Hours 小时
4. Day-of-Month 月中的天
5. Month 月
6. Day-of-Week 周中的天
7. Year (optional field) 年(可选的域)
一个cron表达式的例子字符串为"0 0 12 ? * WED",这表示“每周三的中午12:00”。
单个子表达式能够包含范围或者列表。例如:前面例子中的周中的天这个域(这里是"WED")能够被替换为"MON-FRI", "MON, WED, FRI"或者甚至"MON-WED,SAT"。
通配符('*')能够被用来表示域中“每一个”可能的值。所以在"Month"域中的*表示每月,而在Day-Of-Week域中的*则表示“周中的每一天”。
全部的域中的值都有特定的合法范围,这些值的合法范围至关明显,例如:秒和分域的合法值为0到59,小时的合法范围是0到23,Day-of-Month中值得合法凡范围是0到31,可是须要注意不一样的月份中的天数不一样。月份的合法值是0到11。或者用字符串JAN,FEB MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV 及DEC来表示。Days-of-Week能够用1到7来表示(1=星期日)或者用字符串SUN, MON, TUE, WED, THU, FRI 和SAT来表示.
'/'字符用来表示值的增量,例如, 若是分钟域中放入'0/15',它表示“每隔15分钟,从0开始”,若是在分钟域中使用'3/20',则表示“小时中每隔20分钟,从第3分钟开始”或者另外相同的形式就是'3,23,43'。
'?'字符能够用在day-of-month及day-of-week域中,它用来表示“没有指定值”。这对于须要指定一个或者两个域的值而不须要对其余域进行设置来讲至关有用。
'L' 字符能够在day-of-month及day-of-week中使用,这个字符是"last"的简写,可是在两个域中的意义不一样。例如,在day-of- month域中的"L"表示这个月的最后一天,即,一月的31日,非闰年的二月的28日。若是它用在day-of-week中,则表示"7"或者"SAT"。可是若是在day-of-week域中,这个字符跟在别的值后面,则表示"当月的最后的周XXX"。例如:"6L" 或者 "FRIL"都表示本月的最后一个周五。当使用'L'选项时,最重要的是不要指定列表或者值范围,不然会致使混乱。
'W' 字符用来指定距离给定日最接近的周几(在day-of-week域中指定)。例如:若是你为day-of-month域指定为"15W",则表示“距离月中15号最近的周几”。
'#'表示表示月中的第几个周几。例如:day-of-week域中的"6#3" 或者 "FRI#3"表示“月中第三个周五”。
做为一个例子,下面的Quartz.NET克隆表达式将在星期一到星期五的天天上午10点15分执行一个做业。
0 15 10 ? * MON-FRI
下面的表达式
0 15 10 ? * 6L 2007-2010
将在2007年到2010年的每月的最后一个星期五上午10点15分执行做业。你不可能用SimpleTrigger来作这些事情。你能够用二者之中的任何一个,但哪一个跟合适则取决于你的调度须要。