Quartz.NET V2.6.2版本简单使用
一、Nuget安装命令
Install-Package Quartz -Version 2.6.2
二、代码实现
Program.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; namespace ConsoleApplication { class Program { static void Main(string[] args) { //创建一个调度器工厂 ISchedulerFactory iFactory = new StdSchedulerFactory(); //从调度器工厂中获取调度器 IScheduler iScheduler = iFactory.GetScheduler(); //创建作业(TaskStart是实现了IJob接口的类) IJobDetail iDetail = JobBuilder.Create<TaskStart>().Build(); //添加作业名称及分组名称 iDetail = iDetail.GetJobBuilder().WithIdentity("Job", "Group").Build(); //创建触发器1 ITrigger iTrigger = TriggerBuilder.Create().Build(); //添加触发器名称及分组名称 iTrigger = iTrigger.GetTriggerBuilder().WithIdentity("Trigger", "Group").Build(); //添加触发时间(下面是每天下午4点触发一次) iTrigger = iTrigger.GetTriggerBuilder().WithCronSchedule("* * 16 ? * *").Build(); //将作业与触发器添加到调度器中 iScheduler.ScheduleJob(iDetail, iTrigger); //启动调度器 iScheduler.Start(); Console.ReadKey(); } } public class TaskStart2 : IJob { public void Execute(IJobExecutionContext context) { //要执行的代码 } } }
三、XML配置实现
创建quartz.config

#指定调度器的实例名称
quartz.scheduler.instanceName = iScheduler
#格式:完整命名空间的类名,程序集名称(应该是解析Xml文件的类吧,基本不用改)
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
#XML配置文件的位置
quartz.plugin.xml.fileNames = ~/quartz_jobs.xml
创建quartz_jobs.xml

<?xml version="1.0" encoding="utf-8" ?> <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData"> <processing-directives> <overwrite-existing-data>true</overwrite-existing-data> </processing-directives> <schedule> <!--作业节点,每个作业则对应一个job节点(多个任务请创建多个job节点即可)--> <job> <!--任务名称,同一个group中多个job的name不能相同,若未设置group则所有未设置group的job为同一个分组--> <name>Job1</name> <!--任务所属分组,用于标识任务所属分组--> <group>Group1</group> <!--任务描述,用于描述任务具体内容--> <description>作业1</description> <!--任务类型,任务的具体类型及所属程序集,格式:实现了IJob接口的包含完整命名空间的类名,程序集名称--> <job-type>ConsoleApplication.TaskStart,ConsoleApplication</job-type> <!--表示该作业是否长久的,具体作用不详,默认为true--> <durable>true</durable> <!--字面意思是恢复,具体作用不详,默认为false。--> <recover>false</recover> <!--传进去的参数--> <job-data-map> <!--参数StartDate--> <entry> <key>StartDate</key> <value>2018-11-01</value> </entry> <!--参数EndDate--> <entry> <key>EndDate</key> <value>2018-11-23</value> </entry> </job-data-map> </job> <!-- 任务触发器,用于定义使用何种方式出发任务(job),同一个job可以定义多个trigger ,多个trigger 各自独立的执行调度,每个trigger 中必须且只能定义一种触发器类型(calendar-interval、simple、cron)--> <trigger> <!--复杂任务触发器(使用cron表达式定制任务调度)--> <cron> <!--触发器名称,同一个group中触发器名称不能相同--> <name>Trigger</name> <!--触发器分组名称,表示该触发器所属分组--> <group>Group1</group> <!--触发器描述,用于描述触发器具体内容--> <description>触发器1</description> <!--要调度的作业名称,必须与 job 节点中的 name 相同--> <job-name>Job1</job-name> <!--要调度的作业分组名称,必须与 job 节点中的 group 相同--> <job-group>Group1</job-group> <!--cron表达式(下面是每天下午两点执行一次)--> <cron-expression>0 0 14 * * ? *</cron-expression> </cron> </trigger> <job> <name>Job2</name> <group>Group2</group> <description>作业2</description> <job-type>CarTravelLogStatisticsService.Job.TaskStart2,CarTravelLogStatisticsService</job-type> <durable>true</durable> <recover>false</recover> </job> <trigger> <!--简单任务的触发器,可以调度用于重复执行的任务--> <simple> <!-- 触发器名称--> <name>Trigger2</name> <!--触发器分组名称,表示该触发器所属分组--> <group>Group2</group> <!--触发器描述,用于描述触发器具体内容--> <description>触发器2</description> <!--要调度的作业名称,必须与 job 节点中的 name 相同--> <job-name>Job2</job-name> <!--要调度的作业分组名称,必须与 job 节点中的 group 相同--> <job-group>Group2</job-group> <!--任务重复执行次数(-1:表示无限次执行,0:不重复执行,1:重复执行一次)--> <repeat-count>0</repeat-count> <!--任务重复执行触发间隔(毫秒)(0:立即重复执行,1000:1秒后再重复执行)--> <repeat-interval>0</repeat-interval> </simple> </trigger> </schedule> </job-scheduling-data>
Program.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Quartz; using Quartz.Impl; namespace ConsoleApplication { class Program { static void Main(string[] args) { //创建一个调度器工厂 ISchedulerFactory iFactory = new StdSchedulerFactory(); //从调度器工厂中获取调度器 IScheduler iScheduler = iFactory.GetScheduler(); //启动调度器 iScheduler.Start(); Console.ReadKey(); } } public class TaskStart : IJob { public void Execute(IJobExecutionContext context) { DateTime startTime = Convert.ToDateTime(context.JobDetail.JobDataMap["StartDate"]); DateTime endTime = Convert.ToDateTime(context.JobDetail.JobDataMap["EndDate"]); Console.WriteLine("开始时间:" + startTime.ToString("yyyy-MM-dd HH:mm:ss:fff")); Console.WriteLine("结束时间:" + endTime.ToString("yyyy-MM-dd HH:mm:ss:fff")); } } public class TaskStart2 : IJob { public void Execute(IJobExecutionContext context) { Console.WriteLine("现在的时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")); } } }
四、cron表达式规则
1、 一个cron表达式有至少6个(或7个)由空格分隔的时间元素,按顺序依次为:[秒] [分] [小时] [日] [月] [周] [年]
2、字段间顺序和格式如下
序号 |
必填 |
意义 |
数据格式 |
特殊字符 |
1 |
是 |
秒 |
0-59 |
, - * / |
2 |
是 |
分 |
0-59 |
, - * / |
3 |
是 |
时 |
0-23 |
, - * / |
4 |
是 |
日 |
1-31 |
, - * ? / L W C |
5 |
是 |
月 |
1-12 JAN-DEC |
, - * / |
6 |
是 |
周 |
1-7 SUN-SAT |
, - * ? / L C # |
7 |
否 |
年 |
1970-2099 |
, - * / |
其中,周取值:1=周日~7=周六,1=SUN,2=MON,3=TUE,4=WED,5=THU,6=FRI,7=SAT。
3、通配符说明:
1) * 表示所有值,例如:分设置为"*",表示每一分钟都会触发。
2) ? 表示不指定值,使用场景不需要关心当前的这个元素。例如:要在每月的10号触发一个操作,但不关心是周几,所以周设置为"?",具体设置为 0 0 0 10 * ?。
3) - 表示区间,例如:在小时上设置"10-12",表示10,11,12点都会触发。注意:这里的区间是包头包围的,比如配置是:0 0/15 9-22 * * ?,则表示9:00~22:59,每15分钟触发一次。
4) , 表示指定多个值(列表),例如:在周字段上设置"MON,WED,FRI",表示周一、周三、周五都会触发。
5) / 用于递增触发,例如:在秒上面设置"5/15",表示从5秒开始,每增15秒触发一次(5,20,35,50)。
6) L 表示最后的意思。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年[leap]);在周字段上表示星期六,相当于"7"或"SAT"。如果在"L"前加上数字,则表示该数据的最后一个。例如:在周字段上设置"6L"这样的格式,则表示“本月最后一个星期五”。
7) W 表示离指定日期的最近那个工作日(周一至周五)。例如:在日字段上设置"15W",表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发,如果15号是周未,则找最近的下周一(16号)触发。如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为"1W",它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注:"W"前只能设置具体的数字,不允许区间"-")。
8) # 序号,表示每月的第几个周几。例如:在周字段上设置"6#3"表示在每月的第三个周六。注意如果指定"#5",正好第五周没有周六,则不会触发该配置(用在母亲节和父亲节再合适不过了);小提示:'L'和'W'可以一组合使用。如果在日字段上设置"LW",则表示在本月的最后一个工作日触发;周字段的设置,若使用英文字母是不区分大小写的,即MON与mon相同。
4、常用示例:
0 0 12 * * ? 每天12点触发
0 15 10 ? * * 每天10点15分触发
0 15 10 * * ? 每天10点15分触发
0 15 10 * * ? * 每天10点15分触发
0 0 12 ? * WED 每周三12点触发
0 0/30 9-17 * * ? 每天九点到十五店,每半小时触发
0 10,14,16 * * ? 每天上午10点,下午2点、4点触发
0 15 10 * * ? 2005 2005年每天10点15分触发
0 * 14 * * ? 每天下午的2点到2点59分每分触发
0 0/5 14 * * ? 每天下午的2点到2点59分(整点开始,每隔5分触发)
0 0/5 14,18 * * ? 每天下午的 2点到2点59分、18点到18点59分(整点开始,每隔5分触发)
0 0-5 14 * * ? 每天下午的 2点到2点05分每分触发
0 10,44 14 ? 3 WED 3月分每周三下午的 2点10分和2点44分触发
0 15 10 ? * MON-FRI 从周一到周五每天上午的10点15分触发
0 15 10 15 * ? 每月15号上午10点15分触发
0 15 10 L * ? 每月最后一天的10点15分触发
59 59 23 L * ? 每月最后一天的23点59分59秒触发(经测试)
0 15 10 ? * 6L 每月最后一周的星期五的10点15分触发
0 15 10 ? * 6L 2002-2005 从2002年到2005年每月最后一周的星期五的10点15分触发
0 15 10 ? * 6#3 每月的第三周的星期五开始触发
0 0 12 1/5 * ? 每月的第一个中午开始每隔5天触发一次
0 11 11 11 11 ? 每年的11月11号 11点11分触发(光棍节)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器