任务调度系统Quartz.net详解1-基本流程及Core表达式

Quartz.NET是一个强大、开源、轻量级的任务调度框架。常见的定时任务比如:

Quartz包含以下5个基本部分:

  1. Scheduler:调度器,也可认为是quartz工作时的独立容器
  2. Trigger:触发器,定义了调度任务的时间规则,也就是什么时候去执行任务
  3. Job:需要执行的任务
  4. ThreadPool:线程池(不是clr中的线程池),任务最终交给线程池中的线程执行
  5. JobStore:分为RAWStore和DbStore两种,job和trigger都存放在JobStore中

Quartz的基本工作流程

scheduler是quartz的独立运行容器,trigger和job都可以注册在scheduler容器中,其中trigger是触发器,用于定义调度任务的时间规则,job是被调度的任务,一个job可以有多个触发器,而一个触发器只能属于一个job。

Quartz中有一个调度线程QuartzSchedulerThread,调度线程可以找到将要被触发的trigger,通过trigger找到要执行的job,然后在ThreadPool中获取一个线程来执行这个job。

JobStore主要作用是存放job和trigger的信息。

基本使用

  1. nuget安装Quartz
  1. 定义一个任务
csharp 复制代码
//自定义工作任务,需要实现IJob接口
public class MyJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        await Task.Run(() =>
        {
            Console.WriteLine("我是一个自定义任务");
            Console.WriteLine($"我的任务名称是:{context.JobDetail.Key}");
        });
    }
}
  1. 总体实现
csharp 复制代码
static void Main(string[] args)
{
    //通过调度工厂获取一个调度器实例
    StdSchedulerFactory factory = new StdSchedulerFactory();
    IScheduler scheduler = factory.GetScheduler().Result;

    //创建job
    IJobDetail job = JobBuilder
                    .Create<MyJob>() //创建一个jobBuilder
                    .WithIdentity("jobName", "jonGroup") //辨识名称和分组
                    .WithDescription("增加一个描述")
                    .Build();  //生成IJobDetail

    //创建触发器
    ITrigger trigger = TriggerBuilder
                       .Create() //获取TriggerBuilder
                       //.StartAt(DateBuilder.TodayAt(01,34,00)) //开始时间,今天1点34分0秒(hh,mm,ss)
                       .StartNow() //也可以直接现在执行
                       .ForJob(job) //触发器关联的任务
                       .WithPriority(1) //优先级,触发时间一样时,优先级大的先执行
                       .WithIdentity("TriggerName","TriggerGroup") //辨识名称和分组
                       .WithSimpleSchedule(x=>x
                            .WithIntervalInSeconds(1)
                            .WithRepeatCount(3)
                            .Build()) //调度,一秒执行一次,共执行3次
                       .Build(); //利用TriggerBuilder创建ITrigger

    //start让调度线程启动
    //调度线程可以从jobstore中获取快要执行的trigger,然后获取trigger关联的job,执行job
    scheduler.Start();

    //将job和trigger注册到scheduler中
    //必须,否则不会执行任务
    scheduler.ScheduleJob(job, trigger).Wait();
    Console.WriteLine("执行成功");
    Console.ReadLine();
}

TriggerBuilder

TriggerBuilder顾名思义就是用来创建Trigger的。

Trigger的作用是定义Job何时执行。Quartz.net提供了四种触发策略:SimpleScheduleCalendarIntervalScheduleDailyTimeIntervalScheduleCronSchedule

SimpleSchedule

Simpleschedule 是最简单的一种触发策略,它的作用类似于timer,可以设置间隔几秒/几分钟/几小时执行一次,如创建一秒执行一次的触发器如下

csharp 复制代码
.WithSimpleSchedule(x=>x
     .WithIntervalInSeconds(1)
     .WithRepeatCount(3)
     .Build()) //调度,一秒执行一次,共执行3次

CalendarIntervalSchedule

CalendarIntervalSchedule可以实现时分秒天周月年的维度上执行轮询。如创建一个月执行一次的触发器如下

.WithCalendarIntervalSchedule(x => x.WithIntervalInMonths(1)) //一月执行一次

DailyTimeIntervalSchedule

主要用于指定每周的某几天执行,如我们想让每周的周六周日的8:00-20:00,每两秒执行一次,创建触发器如下

csharp 复制代码
.WithDailyTimeIntervalSchedule(x => x
          .OnDaysOfTheWeek(new DayOfWeek[] { DayOfWeek.Saturday, DayOfWeek.Sunday }) //周六和周日
          .StartingDailyAt(TimeOfDay.HourMinuteAndSecondOfDay(8, 00, 00)) //8点开始
          .EndingDailyAt(TimeOfDay.HourMinuteAndSecondOfDay(20, 00, 00))  //20点结束
          .WithIntervalInSeconds(2)                                       //两秒执行一次,可设置时分秒维度
          .WithRepeatCount(3))                                            //一共执行3+1次

CronSchedul

CronSchedule是应用最多的触发策略,通过Cron表达是我们可以轻松地表示任意的时间节点,下边的代码创建了一个每隔5秒执行一次的触发器

.WithCronSchedule("3/5 * * * * ?") //五秒执行一次

Core表达式

cron表达式有七个部分组成,以此是秒、分、时、天、月、周、年,其中年是可选的。

位置 时间域 允许值 特殊值
1 0-59 , - * /
2 分钟 0-59 , - * /
3 小时 0-23 , - * /
4 日期 1-31 , - * ? / L W C
5 月份 1-12 , - * /
6 星期 1-7 , - * ? / L C #
7 年份(可选) 1-31 , - * /

特殊值含义

符号 含义
* 可用在所有字段中,表示对应时间域的每一个时刻
? 该字符只在日期和星期字段中使用,它通常指定为"无意义的值",相当于点位符
- 表达一个范围,如在小时字段中使用"10-12",则表示从10到12点
, 表达一个列表值,如在星期字段中使用"MON,WED,FRI",则表示星期一,星期三和星期五
/ x/y表达一个等步长序列,x为起始值,y为增量步长值。如5/15在分钟字段中表示5,20,35,50
L 该字符只在日期和星期字段中使用,代表"Last"的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示"这个月的最后X天",例如,6L表示该月的最后星期五
w 该字符只能出现在日期字段里,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围
lw 在日期字段可以组合使用LW,它的意思是当月的最后一个工作日
# 该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发

案例:

表示式 说明
0 0 12 * * ? 每天12点运行
0 15 10 ? * * 每天10:15运行
0 15 10 * * ? 每天10:15运行
0 15 10 * * ? * 每天10:15运行
0 15 10 * * ? 2008 在2008年的每天10:15运行
0 * 14 * * ? 每天14点到15点之间每分钟运行一次,开始于14:00,结束于14:59。
0 0/5 14 * * ? 每天14点到15点每5分钟运行一次,开始于14:00,结束于14:55。
0 0/5 14,18 * * ? 每天14点到15点每5分钟运行一次,此外每天18点到19点每5钟也运行一次。
0 0-5 14 * * ? 每天14:00点到14:05,每分钟运行一次。
0 10,44 14 ? 3 WED 3月每周三的14:10分和14: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 2007-2009 在2007,2008,2009年每个月的最后一个星期五的10:15分运行。
0 15 10 ? * 6#3 每月第三个星期五的10:15分运行。
相关推荐
He BianGu1 天前
【笔记】在WPF中Binding里的详细功能介绍
笔记·wpf
He BianGu1 天前
【笔记】在WPF中 BulletDecorator 的功能、使用方式并对比 HeaderedContentControl 与常见 Panel 布局的区别
笔记·wpf
123梦野2 天前
WPF——效果和可视化对象
wpf
He BianGu2 天前
【笔记】在WPF中Decorator是什么以及何时优先考虑 Decorator 派生类
笔记·wpf
时光追逐者3 天前
一款专门为 WPF 打造的开源 Office 风格用户界面控件库
ui·开源·c#·.net·wpf
He BianGu3 天前
【笔记】介绍 WPF XAML 中 Binding 的 StringFormat详细功能
笔记·wpf
Rotion_深3 天前
C# WPF使用线程池运行Action方法
c#·wpf·线程池
攻城狮CSU4 天前
WPF 深入系列.2.布局系统.尺寸属性
wpf
攻城狮CSU4 天前
WPF 深入系列.2.布局系统.布局控件.Grid
wpf
玖笙&4 天前
✨WPF编程基础【1.3】:XAML 名称空间
c++·wpf·visual studio