定时调度可以理解为定时执行某个方法或逻辑代码,Timer也可以实现类似的功能。Quartz就是启动定时任务的框架,直接在项目引用后就可以调用。
准备工作:
项目安装Quartz
代码实现:
1.声明Scheduler(作业调度池)
2.声明JobDetail
3.声明Trigger
4.将JobDetail和Trigger添加到作业调度池中
下面是详细的步骤:
项目引用Quartz,使用NuGet包管理器安装,我安装的Quartz是3.0.7版本(不同的版本,对应的api调用方式不一样2.x和3.x区别挺大),对应的.NETFramework版本要求至少为4.5.2。
代码实现部分:
1.Scheduler 作业调度器
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
await scheduler.Start();
2.JobBuilder 根据设置,生成一个详细作业信息(JobDetail)。
IJobDetail jobDetail1 = JobBuilder.Create<JobDemo>().WithIdentity("testjob", "group1").WithDescription("我是testjob").Build();
jobDetail1.JobDataMap.Add("name", "张三");
jobDetail1.JobDataMap.Add("age", "20");
3.TriggerBuilder 根据规则,生产对应的Trigger
//程序启动2秒后执行,间隔3秒执行一次,一直执行
ITrigger trigger = TriggerBuilder.Create().WithIdentity("testtrigger", "group1").StartAt(new DateTimeOffset(DateTime.Now.AddSeconds(2)))
.WithCronSchedule("0/3 * * * * ?").WithDescription("我是testjob的触发器").Build();
4.加入作业调度池中
await scheduler.ScheduleJob(jobDetail1, trigger);
完整代码如下:
public async static Task Init()
{
try
{
Console.WriteLine("初始化scheduler.....");
//1.Scheduler 作业调度器
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
await scheduler.Start();
//2.JobBuilder 根据设置,生成一个详细作业信息(JobDetail)。
IJobDetail jobDetail1 = JobBuilder.Create<JobDemo>().WithIdentity("testjob", "group1").WithDescription("我是testjob").Build();
jobDetail1.JobDataMap.Add("name", "张三");
jobDetail1.JobDataMap.Add("age", "20");
//3.TriggerBuilder 根据规则,生产对应的Trigger
//程序启动2秒后执行,间隔3秒执行一次,一直执行
ITrigger trigger = TriggerBuilder.Create().WithIdentity("testtrigger", "group1").StartAt(new DateTimeOffset(DateTime.Now.AddSeconds(2)))
.WithCronSchedule("0/3 * * * * ?").WithDescription("我是testjob的触发器").Build();
//4.加入作业调度池中
await scheduler.ScheduleJob(jobDetail1, trigger);
Console.WriteLine("作业添加完成.....");
}
catch (Exception)
{
throw;
}
}
其中自定义逻辑是写在第二步的JobDemo类中,代码如下:
//IJob 作业接口,继承并实现Execute, 编写执行的具体作业逻辑。
public class JobDemo : IJob
{
public async Task Execute(IJobExecutionContext context)
{
try
{
await Task.Run(() =>
{
Console.WriteLine();
JobDataMap map = context.JobDetail.JobDataMap;
Console.WriteLine(map.Get("name"));
Console.WriteLine(map.Get("age"));
Console.WriteLine(DateTime.Now.ToString("r"));
Console.WriteLine();
});
}
catch (Exception)
{
throw;
}
}
}
以上代码实现的逻辑是程序启动2秒后开始打印在第二步中为jobDetail1添加的参数信息。每隔3秒打印一次,只要程序不停止,就一直执行。
如下所示:
用法的补充和扩展:
在第三步,创建Trigger,是为了控制程序运行的周期,运行次数等等
上面代码示例中使用的是Cron表达式,详细用法参考:https://www.cnblogs.com/sunjie9606/archive/2012/03/15/2397626.html
同时网上也有生成Cron表达式的工具,可以根据选择的时间自动生成表达式:https://cron.qqe2.com/
除了Cron表达式外,还有另外的写法来控制程序运行的周期,比如Simple模式。代码如下:
//程序启动立刻执行,间隔一秒执行一次,一共执行2+1次
ITrigger trigger = TriggerBuilder.Create().WithIdentity("testtrigger", "group1").StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(1).WithRepeatCount(2)).WithDescription("我是testjob的触发器").Build();
这段代码可以替换上面实例中第三部分的代码,实现的逻辑是程序启动后立刻执行任务,每隔一秒钟执行一次,一共重复2次,加上刚开始执行的一次,一共会执行3次。
StartNow(),立即执行作业任务
WithIntervalInSeconds(1),一秒执行一次
WithRepeatCount(2),重复执行两次,这里也可以用RepeatForever(),表示永远执行下去,不限制执行次数。
还有很多其他的api可以通过自行查看,查看方法如下:
关于监听Listener
Quartz的监听器用于当任务调度中所关注事件的发生时,能够及时获取这一事件的通知。类似于任务执行过程中邮件、短信类的提醒。Quartz监听器主要有SchedulerListener、 TriggerListener、JobListener三种,分别表示调度器、触发器、任务对应的监听器。
三者使用方法类似。下面以TriggerListener为例,写一个类说明用法:
MyTriggerListener类:
public class MyTriggerListener : ITriggerListener
{
public string Name => "MyTriggerListener";
public async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine("job完成时调用");
Console.WriteLine();
});
}
public async Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine("job执行时调用");
});
}
public async Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine("错过触发时调用(例:线程不够用的情况下)");
});
}
public async Task<bool> VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
//Trigger触发后,job执行时调用本方法。true即否决,job后面不执行。
await Task.Run(() =>
{
Console.WriteLine("Trigger触发后,job执行时调用本方法。");
});
return false;
}
}
自定义的MyTriggerListener实现后,需要添加监听器到指定的trigger,如图所示:
代码:
scheduler.ListenerManager.AddTriggerListener(new MyTriggerListener());//添加TriggerListener
添加完成后,再次启动项目,可以看到在控制台打印了相关信息:
其他两个监听器用法类似。
关于监听器可以参考下面链接,虽然是java版本的,但是很多东西是相同的,毕竟.Net的Quartz是由java版本变化而来。
https://www.cnblogs.com/mengrennwpu/p/7191229.html