前言
大家好,我是不自由的小码,这次要给大家分享的是基于Quartz.Net实现定时任务。timer这个东西相信大家都不会陌生,然而,timer的局限性,注定了在复杂任务调度下以及多任务长时间运行下,很容易出现无法达到预期的效果。
一、Quartz.Net是什么?
Quartz.Net是任务调度框架。根据官方的说法,它具有以下特点:
1.【运行时环境】可以嵌入在应用程序中运行,甚至可以实例化为独立程序集群(具有负载平衡和故障转移功能)
2.【作业调度】作业计划在给定触发器发生时运行,触发器支持多种计划选项
3.【作业执行】作业可以是实现简单 IJob 接口的任何 .NET 类,为作业可以执行的工作留下了无限的可能性
4.【作业持久性】可以实现作业存储来提供各种机制来存储作业,内存中和多个关系数据库开箱即用
5.【聚类】内置支持对工作负载平衡和正常故障转移
6.【侦听器和插件】应用程序可以通过实现一个或多个侦听器接口来捕获调度事件以监视或控制作业/触发器行为
二、Quartz.Net应用
1.引入库
打开VS2022通过Nuget搜索并且安装Quartz.Net。
using Quartz;
using Quartz.Impl;
2.任务调度配置类
JobScheduler配置类,下图很好解析了,一个任务调度的原理:
一旦调度程序被实例化,就可以启动它,将其置于待机模式并关闭。请注意,一旦调度程序关闭,如果不重新实例化,就无法重新启动它。触发器在计划程序启动之前不会触发(作业不会执行),也不会在计划程序处于暂停状态时触发。
public class JobScheduler
{
public static void Start()
{
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Start();
IJobDetail job = JobBuilder.Create<InventoryJob>().Build();
ITrigger trigger1 = TriggerBuilder.Create()
.WithDailyTimeIntervalSchedule
(s =>
s.WithIntervalInHours(24)
.OnEveryDay()
.StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(0, 0))
)
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.WithSimpleSchedule(x => x.WithIntervalInSeconds(5).RepeatForever())
.Build();
ITrigger CronTrigger = TriggerBuilder.Create()
.WithCronSchedule(Com.corn)
.Build();
scheduler.ScheduleJob(job, CronTrigger);
}
}
3.作业实现类
InventoryJob类要继承于IJob,然后创建执行方法Execute(),该类是任务调度触发后第一时间执行的方法,一般应用于业务逻辑。
public class InventoryJob : IJob
{
public void Execute(IJobExecutionContext context)
{
//to do something
}
}
4.配置Corn表达式
App.config文件中配置corn代码,配置是为了更灵活,没有别的意义,也可以写死在代码中。
<appSettings>
<!--Corn表达式,每两小时的35分执行一次-->
<add key="Corn" value="0 35 */2 * * ?" />
</appSettings>
初始化corn的值,也就是拿到我这个任务要在什么时间点执行。
Com.corn = ConfigurationManager.AppSettings["Corn"] != null ? ConfigurationManager.AppSettings["Corn"] : "0 35 0/1 * * ?";
表达式最终会在调度配置类中应用【JobScheduler】
ITrigger CronTrigger = TriggerBuilder.Create()
.WithCronSchedule(**Com.corn**)
.Build();
5.启动
Com.InitPara();//初始化配置参数,如初始化上面的Corn表达式。
JobScheduler.Start();
6.关闭
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Shutdown(true);//true 任务都执行完成以后在关闭 false 直接关闭
6.暂停、挂起
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Standby();
6.强制停止任务
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Shutdown(false);//true 任务都执行完成以后在关闭 false 直接关闭
三、注意事项
如果业务框架是CS模式,比如Winform、WPF下,在关闭窗体的时候需要考虑,任务管理器后台进行会不会结束掉,一般的Close,Exit,等都会出现杀不掉情况,使用下面代码进行Kill进程即可:
Process.GetCurrentProcess().Kill();