Quartz.Net初探

     想必大家在工作中经常会遇到这样类似的需求,在某个时间或者需要不间断的执行某个业务动作去满足任务需求。例如,我们写了一个job,定时去处理一些任务,在没有了解到Quartz.Net之前,我是这样做的,进行轮询处理,如图:

 

是不是感觉很low啊。前些日子,了解到了Quartz.Net,它是一个强大的开源任务调度器,它提供的触发器以及Cron表达式能够很好的满足我们在日常开发中遇到的定时服务的工作处理,为了在以后工作中更好的使用它,我对它的基本使用方法进行了整理,当然下面所讲到的只是它的一些常用功能,至于更强大的功能,例如远程调度等等,还需要后续再进一步了解。但是在我看来,已能够满足我们在日常中的大部分开发工作。

1、建立如下解决方案,如图

 

正如大家看到的,我在解决方案中添加了QuartzTest的控制台项目进行demo演示,需要说明的是,大家可通过Nuget将Quartz包添加至项目当中。根据Quartz的常用操作,整理出了 BaseJob以及QuartzHelper帮助类。

BaseJob类中包含了要执行任务的基本信息,例如Job名称,组名,触发器名称,执行间隔时间等等信息,在实现具体Job时,只要继承该基类并使用相应的构造函数对Job基本信息进行初始化即可。

如下图:

QuartzHelper中对常用的任务调度方法进行了整理,这里我们将TestJob添加至调度器并开始任务的执行,如下图:

该Demo以及整理的完整代码如下:

  1  /// <summary>
  2     /// 任务基类
  3     /// </summary>
  4     public abstract class BaseJob : IJob
  5     {
  6         private string _jobName = string.Empty;
  7         private string _gropName = string.Empty;
  8         private string _triggerName = string.Empty;
  9         private int _intervalTime;
 10         private DateTimeOffset _startTime;
 11         private DateTimeOffset? _endTime;
 12         private int _repeatCount;
 13         private string _cronExpression;
 14 
 15 
 16         /// <summary>
 17         /// 无参构造函数
 18         /// </summary>
 19         public BaseJob()
 20         {
 21 
 22         }
 23       
 24 
 25         /// <summary>
 26         /// 构造函数
 27         /// </summary>
 28         /// <param name="jobName">任务名称</param>
 29         /// <param name="triggerName">触发器名称</param>
 30         /// <param name="gropName">任务组名称</param>
 31         /// <param name="intervalTime">间隔时间</param>
 32         public BaseJob(string jobName, string triggerName, string gropName, int intervalTime)
 33         {
 34             this._jobName = jobName;
 35             this._triggerName = triggerName;
 36             this._gropName = gropName;
 37             this._intervalTime = intervalTime;
 38         }
 39 
 40 
 41         /// <summary>
 42         /// 构造函数
 43         /// </summary>
 44         /// <param name="jobName">任务名称</param>
 45         /// <param name="triggerName">触发器名称</param>
 46         /// <param name="gropName">任务组名称</param>
 47         /// <param name="intervalTime">间隔时间</param>
 48         /// <param name="cronExpression">cron表达式</param>
 49         public BaseJob(string jobName, string triggerName, string gropName, int intervalTime, string cronExpression)
 50         {
 51             this._jobName = jobName;
 52             this._triggerName = triggerName;
 53             this._gropName = gropName;
 54             this._intervalTime = intervalTime;
 55             this._cronExpression = cronExpression;
 56         }
 57 
 58 
 59         /// <summary>
 60         /// 构造函数
 61         /// </summary>
 62         /// <param name="jobName">任务名称</param>
 63         /// <param name="triggerName">触发器名称</param>
 64         /// <param name="gropName">任务组名称</param>
 65         /// <param name="intervalTime">间隔时间</param>
 66         /// <param name="startTime">开始时间</param>
 67         /// <param name="endTime">结束时间</param>
 68         public BaseJob(string jobName, string triggerName, string gropName, int intervalTime, DateTimeOffset startTime, DateTimeOffset? endTime)
 69         {
 70             this._jobName = jobName;
 71             this._triggerName = triggerName;
 72             this._gropName = gropName;
 73             this._intervalTime = intervalTime;
 74             this._startTime = startTime;
 75             this._endTime = endTime;
 76         }
 77 
 78 
 79         /// <summary>
 80         /// 构造函数
 81         /// </summary>
 82         /// <param name="jobName">任务名称</param>
 83         /// <param name="triggerName">触发器名称</param>
 84         /// <param name="gropName">任务组名称</param>
 85         /// <param name="intervalTime">间隔时间</param>
 86         /// <param name="startTime">开始时间</param>
 87         /// <param name="endTime">结束时间</param>
 88         /// <param name="repeatCount">重复次数</param>
 89         public BaseJob(string jobName, string triggerName, string gropName, int intervalTime, DateTimeOffset startTime, DateTimeOffset? endTime, int repeatCount)
 90         {
 91             this._jobName = jobName;
 92             this._triggerName = triggerName;
 93             this._gropName = gropName;
 94             this._intervalTime = intervalTime;
 95             this._startTime = startTime;
 96             this._endTime = endTime;
 97             this._repeatCount = repeatCount;
 98         }
 99 
100 
101 
102         /// <summary>
103         /// 任务名称
104         /// </summary>
105         public string JobName
106         {
107             get { return _jobName; }
108             set { _jobName = value; }
109         }
110 
111         /// <summary>
112         /// 触发器名称
113         /// </summary>
114         public string TriggerName
115         {
116             get { return _triggerName; }
117             set { _triggerName = value; }
118         }
119 
120         /// <summary>
121         /// 任务组名称
122         /// </summary>
123         public string GropName
124         {
125             get { return _gropName; }
126             set { _gropName = value; }
127         }
128 
129         /// <summary>
130         /// 执行间隔时间
131         /// </summary>
132         public int IntervalTime
133         {
134             get { return _intervalTime; }
135             set { _intervalTime = value; }
136         }
137 
138         /// <summary>
139         /// 开始时间
140         /// </summary>
141         public DateTimeOffset StartTime
142         {
143             get { return _startTime; }
144             set
145             {
146                 if (value == null || value == DateTime.MinValue) _startTime = SystemTime.UtcNow();
147                 else _startTime = value;
148             }
149         }
150 
151         /// <summary>
152         /// 结束时间
153         /// </summary>
154         public DateTimeOffset? EndTime
155         {
156             get { return _endTime; }
157             set { _endTime = value; }
158         }
159 
160         /// <summary>
161         /// 重复执行次数
162         /// </summary>
163         public int RepeatCount
164         {
165             get { return _repeatCount; }
166             set { _repeatCount = value; }
167         }
168 
169         /// <summary>
170         /// Cron表达式
171         /// </summary>
172         public string CronExpression
173         {
174             get { return _cronExpression; }
175             set { _cronExpression = value; }
176         }
177 
178 
179         /// <summary>
180         /// 任务执行
181         /// </summary>
182         /// <param name="context">任务执行上下文</param>
183         public abstract void Execute(IJobExecutionContext context);
184     }

   

  1  /// <summary>
  2     /// Quartz帮助类
  3     /// </summary>
  4     public class QuartzHelper
  5     {
  6         private static ISchedulerFactory _schedulerFactory;
  7         private static IScheduler _scheduler;
  8 
  9         /// <summary>
 10         /// 构造函数
 11         /// </summary>
 12         static QuartzHelper()
 13         {
 14             _schedulerFactory = CreateSchedulerFactory();
 15             _scheduler = GetScheduler();
 16         }
 17 
 18         #region 获取服务器使用的调度程序
 19         /// <summary>
 20         /// 获取服务器使用的调度程序。
 21         /// </summary>
 22         /// <returns></returns>
 23         protected static IScheduler GetScheduler()
 24         {
 25             return _schedulerFactory.GetScheduler();
 26         }
 27         #endregion
 28 
 29         #region 创建调度器工厂
 30         /// <summary>
 31         /// 创建调度器工厂。
 32         /// </summary>
 33         /// <returns></returns>
 34         protected static ISchedulerFactory CreateSchedulerFactory()
 35         {
 36             return new StdSchedulerFactory();
 37         }
 38         #endregion
 39 
 40         #region 委托调度器,启动实例
 41         /// <summary>
 42         /// 委托调度器,启动实例。
 43         /// </summary>
 44         public static void Start()
 45         {
 46             try
 47             {
 48                 _scheduler.Start();
 49             }
 50             catch (Exception ex)
 51             {
 52                 throw ex;
 53             }
 54         }
 55         #endregion
 56 
 57         #region 委托调度器,停止实例
 58         /// <summary>
 59         ///  委托调度器,停止实例。
 60         /// </summary>
 61         public static void Stop()
 62         {
 63             try
 64             {
 65                 if (!_scheduler.IsShutdown)
 66                     _scheduler.Shutdown(true);
 67             }
 68             catch (Exception ex)
 69             {
 70                 throw ex;
 71             }
 72         }
 73         #endregion
 74 
 75         #region 暂停调度器中所有的活动
 76         /// <summary>
 77         /// 暂停调度器中所有的活动。
 78         /// </summary>
 79         public static void Pause()
 80         {
 81             try
 82             {
 83                 _scheduler.PauseAll();
 84             }
 85             catch (Exception ex)
 86             {
 87                 throw ex;
 88             }
 89         }
 90         #endregion
 91 
 92         #region 恢复所有活动
 93         /// <summary>
 94         /// 恢复所有活动。
 95         /// </summary>
 96         public static void Resume()
 97         {
 98             try
 99             {
100                 _scheduler.ResumeAll();
101             }
102             catch (Exception ex)
103             {
104                 throw ex;
105             }
106         }
107         #endregion
108 
109         #region 添加任务(任务间隔时间单位:小时)
110         /// <summary>
111         /// 添加任务(任务间隔时间单位:小时)
112         /// </summary>
113         /// <typeparam name="T">具体任务</typeparam>
114         public static void AddJobForHours<T>()
115              where T : BaseJob, new()
116         {
117             try
118             {
119                 T job = new T();
120                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
121                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartNow()
122                                                               .WithSimpleSchedule(x => x.WithIntervalInHours(job.IntervalTime).RepeatForever())
123                                                               .Build();
124                 _scheduler.ScheduleJob(jobDetail, trigger);
125             }
126             catch (Exception ex)
127             {
128                 throw ex;
129             }
130         }
131         #endregion
132 
133         #region  添加任务(任务间隔时间单位:分钟)
134         /// <summary>
135         /// 添加任务(任务间隔时间单位:分钟)
136         /// </summary>
137         /// <typeparam name="T">具体任务</typeparam>
138         public static void AddJobForMinutes<T>()
139               where T : BaseJob, new()
140         {
141             try
142             {
143                 T job = new T();
144                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
145                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartNow()
146                                                               .WithSimpleSchedule(x => x.WithIntervalInMinutes(job.IntervalTime).RepeatForever())
147                                                               .Build();
148                 _scheduler.ScheduleJob(jobDetail, trigger);
149             }
150             catch (Exception ex)
151             {
152                 throw ex;
153             }
154         }
155         #endregion
156 
157         #region 添加任务(任务间隔时间单位:秒)
158         /// <summary>
159         /// 添加任务(任务间隔时间单位:秒)
160         /// </summary>
161         /// <typeparam name="T">具体任务</typeparam>
162         public static void AddJobForSeconds<T>()
163              where T : BaseJob, new()
164         {
165             try
166             {
167                 T job = new T();
168                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
169                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartNow()
170                                                               .WithSimpleSchedule(x => x.WithIntervalInSeconds(job.IntervalTime).RepeatForever())
171                                                               .Build();
172                 _scheduler.ScheduleJob(jobDetail, trigger);
173             }
174             catch (Exception ex)
175             {
176                 throw ex;
177             }
178         }
179         #endregion
180 
181         #region 根据开始以及结束时间进行添加任务(任务间隔时间单位:小时)
182         /// <summary>
183         /// 根据开始以及结束时间进行添加任务(任务间隔时间单位:小时)
184         /// </summary>
185         /// <typeparam name="T">具体任务</typeparam>
186         public static void AddJobForHoursStartEndTime<T>()
187              where T : BaseJob, new()
188         {
189             try
190             {
191                 T job = new T();
192                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
193                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
194                                                               .WithSimpleSchedule(x => x.WithIntervalInHours(job.IntervalTime).RepeatForever())
195                                                               .Build();
196                 _scheduler.ScheduleJob(jobDetail, trigger);
197             }
198             catch (Exception ex)
199             {
200                 throw ex;
201             }
202         }
203         #endregion
204 
205         #region 根据开始以及结束时间进行添加任务(任务间隔时间单位:分钟)
206         /// <summary>
207         /// 根据开始以及结束时间进行添加任务(任务间隔时间单位:分钟)
208         /// </summary>
209         /// <typeparam name="T">具体任务</typeparam>
210         public static void AddJobForMinutesStartEndTime<T>()
211               where T : BaseJob, new()
212         {
213             try
214             {
215                 T job = new T();
216                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
217                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
218                                                               .WithSimpleSchedule(x => x.WithIntervalInMinutes(job.IntervalTime).RepeatForever())
219                                                               .Build();
220                 _scheduler.ScheduleJob(jobDetail, trigger);
221             }
222             catch (Exception ex)
223             {
224                 throw ex;
225             }
226         }
227         #endregion
228 
229         #region 根据开始以及结束时间进行添加任务(任务间隔时间单位:秒)
230         /// <summary>
231         /// 根据开始以及结束时间添加任务(任务间隔时间单位:秒)
232         /// </summary>
233         /// <typeparam name="T">具体任务</typeparam>
234         public static void AddJobForSecondsStartEndTime<T>()
235              where T : BaseJob, new()
236         {
237             try
238             {
239                 T job = new T();
240                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
241                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
242                                                               .WithSimpleSchedule(x => x.WithIntervalInSeconds(job.IntervalTime).RepeatForever())
243                                                               .Build();
244                 _scheduler.ScheduleJob(jobDetail, trigger);
245             }
246             catch (Exception ex)
247             {
248                 throw ex;
249             }
250         }
251         #endregion
252 
253         #region 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:小时)
254         /// <summary>
255         /// 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:小时)
256         /// </summary>
257         /// <typeparam name="T">具体任务</typeparam>
258         public static void AddJobForHoursRepeatCount<T>()
259              where T : BaseJob, new()
260         {
261             try
262             {
263                 T job = new T();
264                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
265                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
266                                                               .WithSimpleSchedule(x => x.WithIntervalInHours(job.IntervalTime).WithRepeatCount(job.RepeatCount))
267                                                               .Build();
268                 _scheduler.ScheduleJob(jobDetail, trigger);
269             }
270             catch (Exception ex)
271             {
272                 throw ex;
273             }
274         }
275         #endregion
276 
277         #region 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:分钟)
278         /// <summary>
279         /// 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:分钟)
280         /// </summary>
281         /// <typeparam name="T">具体任务</typeparam>
282         public static void AddJobForMinutesRepeatCount<T>()
283               where T : BaseJob, new()
284         {
285             try
286             {
287                 T job = new T();
288                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
289                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
290                                                               .WithSimpleSchedule(x => x.WithIntervalInMinutes(job.IntervalTime).WithRepeatCount(job.RepeatCount))
291                                                               .Build();
292                 _scheduler.ScheduleJob(jobDetail, trigger);
293             }
294             catch (Exception ex)
295             {
296                 throw ex;
297             }
298         }
299         #endregion
300 
301         #region 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:秒)
302         /// <summary>
303         /// 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:秒)
304         /// </summary>
305         /// <typeparam name="T">具体任务</typeparam>
306         public static void AddJobForSecondsRepeatCount<T>()
307              where T : BaseJob, new()
308         {
309             try
310             {
311                 T job = new T();
312                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
313                 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
314                                                               .WithSimpleSchedule(x => x.WithIntervalInSeconds(job.IntervalTime).WithRepeatCount(job.RepeatCount))
315                                                               .Build();
316                 _scheduler.ScheduleJob(jobDetail, trigger);
317             }
318             catch (Exception ex)
319             {
320                 throw ex;
321             }
322         }
323         #endregion
324 
325         #region 通过Cron表达式添加任务
326         /// <summary>
327         /// 通过Cron表达式添加任务
328         /// </summary>
329         /// <typeparam name="T">具体任务</typeparam>
330         public static void AddJobForCron<T>()
331             where T : BaseJob, new()
332         {
333             try
334             {
335                 T job = new T();
336                 IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
337 
338                 ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
339                                              .WithIdentity(job.TriggerName, job.GropName)
340                                              .WithCronSchedule(job.CronExpression)
341                                              .Build();
342                 _scheduler.ScheduleJob(jobDetail, trigger);
343             }
344             catch (Exception ex)
345             {
346                 throw ex;
347             }
348         }
349         #endregion
350     }
 1   /// <summary>
 2     /// 测试 job
 3     /// </summary>
 4     public class TestJob : BaseJob
 5     {
 6         public TestJob() : base("TestJob", "TestTrigger", "TestGrop",1) { }
 7         public override void Execute(IJobExecutionContext context)
 8         {
 9             try
10             {
11                 Console.WriteLine(string.Format("当前任务执行时间:{0}", DateTime.Now.ToString()));
12                 Thread.Sleep(TimeSpan.FromSeconds(3));
13             }
14             catch (Exception ex)
15             {
16                 throw ex;
17             }
18         }
19     }
  class Program
    {
        static void Main(string[] args)
        {
            QuartzHelper.AddJobForSeconds<TestJob>();
            QuartzHelper.Start();
        }
    }

2、运行解决方案,得到如下结果

 发现是不是任务按照我们所希望的那样运行了,但是大家有没有注意到,TestJob中 有这样一句代码:  Thread.Sleep(TimeSpan.FromSeconds(3));

任务是Sleep3秒钟的,可是我们的Job却一直在执行呢,即使上一次任务还没执行完,它又开始执行了。在我们的实际开发中,我们需要一次任务执行完成后再执行下一次任务。
我们对TestJob 进行改造,代码如下:
 1   /// <summary>
 2     /// 测试 job
 3     /// </summary>
 4     [DisallowConcurrentExecution]
 5     public class TestJob : BaseJob
 6     {
 7         public TestJob() : base("TestJob", "TestTrigger", "TestGrop",1) { }
 8         public override void Execute(IJobExecutionContext context)
 9         {
10             try
11             {
12                 Console.WriteLine(string.Format("当前任务执行时间:{0}", DateTime.Now.ToString()));
13                 Thread.Sleep(TimeSpan.FromSeconds(3));
14             }
15             catch (Exception ex)
16             {
17                 throw ex;
18             }
19         }
20     }

再次运行,如图:

大家发现区别没呢,没错,我们在TestJob类上添加了“DisallowConcurrentExecution”特性,这样,就能在一次任务执行完成后,再进行下次任务的执行了。



勤勤恳恳工作,踏踏实实生活
原文地址:https://www.cnblogs.com/kangkey/p/6941245.html