想必大家在工作中经常会遇到这样类似的需求,在某个时间或者需要不间断的执行某个业务动作去满足任务需求。例如,我们写了一个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”特性,这样,就能在一次任务执行完成后,再进行下次任务的执行了。
原文:http://www.cnblogs.com/kangkey/p/6941245.html