Quartz使用总结
说起调度任务,在.NET中不得不说的就是Quartz.NET了,Quartz.NET是一个强大的、开源的轻量的作业调度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改写。官网地址:https://www.quartz-scheduler.net/
在日常的开发中会经常会使用到调度任务的这种场景,例如数据库在每天的凌晨2点进行一次备份,还有就是对账系统在每隔多久进行一次对账等等。接下来我们就用一个小实例来介绍一下Quartz.NET的基本使用
一.安装
通过nuget管理工具搜索并安装Quartz
二.实例
Quartz中有三个概念,调度器、任务、和触发器。调度器通过任务和触发器完成任务的调度
1.创建任务
public class TimeJob : IJob { public async Task Execute(IJobExecutionContext context) { var jobKey = context.JobDetail.Key;//获取job信息 var triggerKey = context.Trigger.Key;//获取trigger信息 Console.WriteLine($"{DateTime.Now} QuartzJob:==>>自动执行.{jobKey.Name}|{triggerKey.Name}"); await Task.CompletedTask; } }
2.创建调度器
//调度器 IScheduler scheduler; //调度器工厂 ISchedulerFactory factory; //1、创建一个调度器 factory = new StdSchedulerFactory(); scheduler =await factory.GetScheduler(); await scheduler.Start();
3.触发策略
Quartz中有两种触发的策略,SimpleTrigger和CronTrigger
SimpleTrigger
如果您需要让某个作业在特定时间或特定时间执行一次,然后在特定时间间隔重复执行一次,SimpleTrigger应该可以满足您的计划需求。如果您想让扳机在2005年1月13日上午11:23:54触发,然后每十秒钟触发五次
1.为特定时间建立触发器,不要重复:
ISimpleTrigger trigger = (ISimpleTrigger) TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .StartAt(myStartTime) // some Date .ForJob("job1", "group1") // identify job with name, group strings .Build();
2.建立一个特定时间的触发器,然后每十秒钟重复十次:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .StartAt(myTimeToStartFiring) //如果没有给出开始时间(如果省略了这一行),则表示“现在” .WithSimpleSchedule(x => x .WithIntervalInSeconds(10) .WithRepeatCount(10)) //请注意,10次重复将给出总共11次触发 .ForJob(myJob) .Build();
3.建立一个触发器,该触发器将在未来五分钟触发一次:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger5", "group1") .StartAt(DateBuilder.FutureDate(5, IntervalUnit.Minute)) //使用DateBuilder创建时间 .ForJob(myJobKey) .Build();
CronTrigger
Cron表达式
Cron-Expressions用于配置CronTrigger的实例。Cron-Expression是实际上由七个子表达式组成的字符串,它们描述了日程表的各个细节。这些子表达式用空格分隔,代表:
1.秒
2.分钟
3.小时
4.每月的一天
5.月
6.星期几
7.年(可选字段)
完整的cron表达式的示例是字符串0 0 12 ? * WED
-表示“每个星期三的12:00 pm”。
各个子表达式可以包含范围和/或列表。例如,上一个(读为“ WED”)示例中的“星期几”字段可以替换为“ MON-FRI”,“ MON,WED,FRI”,甚至“ MON-WED,SAT”。
通配符(*
字符)可以用来表示此字段的“所有”可能值。因此*
,上一个示例的“月”字段中的字符仅表示“每个月”。一个*
在某一天的周场显然是指“一周中的每一天”。
所有字段都有一组可以指定的有效值。这些值应该非常明显-例如秒和分钟的数字0到59,小时的数字0到23。Day-of-Month可以是0-31之间的任何值,但是您需要注意给定月份中有多少天!可以将月份指定为0到11之间的值,也可以使用字符串JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV和DEC来指定。每周的天数可以指定为1到7之间的值(1 =星期日),也可以使用字符串SUN,MON,TUE,WED,THU,FRI和SAT。
“ /”字符可用于指定值的增量。例如,如果您在“分钟”字段中输入“ 0/15”,则表示“每15分钟,从零分钟开始”。如果您在“分钟”字段中使用“ 3/20”,则表示“每小时每20分钟,从第三分钟开始”,换句话说,与在“分钟”中指定“ 3,23,43”相同场地。
这 '?' 星期几和星期几字段允许使用字符。用于指定“无特定值”。当您需要在两个字段之一中指定某项而不是另一个字段时,这很有用。有关说明,请参见下面的示例(和CronTrigger API文档)。
建立一个触发器,该触发器每天每天从早上8点到下午5点之间每隔一分钟触发一次:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .WithCronSchedule("0 0/2 8-17 * * ?") .ForJob("myJob", "group1") .Build();
建立触发器,每天10:42 am触发:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger3", "group1") .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(10, 42)) .ForJob(myJobKey) .Build();
完整实例
class Program { static void Main(string[] args) { TestRun().Wait(); Console.WriteLine("hello world"); Console.ReadLine(); } private static async Task TestRun() { try { //调度器 IScheduler scheduler; //调度器工厂 ISchedulerFactory factory; //1、创建一个调度器 factory = new StdSchedulerFactory(); scheduler =await factory.GetScheduler(); await scheduler.Start(); //2、创建一个任务 IJobDetail job = JobBuilder.Create<TimeJob>().WithIdentity("job1", "group1").Build(); //3、创建一个触发器 //DateTimeOffset runTime = DateBuilder.EvenMinuteDate(DateTimeOffset.UtcNow); ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .WithCronSchedule("0/5 * * * * ?") //5秒执行一次 //.StartAt(runTime) .Build(); ITrigger trigger2 = TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .WithSimpleSchedule(x=>x.WithInterval(1)) .Build(); //4、将任务与触发器添加到调度器中 await scheduler.ScheduleJob(job, trigger); //5、开始执行 await scheduler.Start(); } catch (Exception ex) { await Console.Error.WriteLineAsync(ex.ToString()); } } }