博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Quartz.NET开源作业调度框架系列(五):AdoJobStore保存job到数据库
阅读量:4692 次
发布时间:2019-06-09

本文共 9674 字,大约阅读时间需要 32 分钟。

Quartz.NET 任务调度的核心元素是 scheduler, trigger 和 job,其中 trigger(用于定义调度时间的元素,即按照什么时间规则去执行任务) 和 job 是任务调度的元数据,scheduler 是实际执行调度的控制器。在Quartz.NET中主要有两种类型的 job:无状态的(stateless)和有状态的(stateful)。对于同一个 trigger 来说,有状态的 job 不能被并行执行,只有上一次触发的任务被执行完之后,才能触发下一次执行。无状态任务一般指可以并发的任务,即任务之间是独立的,不会互相干扰。一个 job 可以被多个 trigger 关联,但是一个 trigger 只能关联一个 job。某些任务需要对数据库中的数据进行增删改处理 , 这些任务不能并发执行,就需要用到无状态的任务 , 否则会造成数据混乱。

  另外有些情况下,我们需要将任务保存到数据库中,特别是有些任务中包含参数,例如累加的任务,如果可以保存到数据库中,即便中间断电或者程序异常重启,中间计算的结果也不会丢失,可以从断点的结果进行运算(首先恢复任务),下面介绍一下如何用AdoJobStore将任务保存到SQL Server数据库中. 

  事先要在数据库上新建一个QRTZ_数据库,并执行SQL建表脚本:

1 RecoveryJob

  是一个无状态的任务,代码如下:

1 using System; 2 using System.Collections.Specialized; 3 using System.Threading; 4 using Common.Logging; 5 using Quartz; 6 using Quartz.Impl; 7 using Quartz.Job; 8 using System.Windows.Forms; 9 namespace  QuartzDemo10 {11     /// 12     /// 无状态的可恢复的任务13     /// 14     public class RecoveryJob : IJob15     {16        17         private const string Count = "count";18         public virtual void Execute(IJobExecutionContext context)19         {20 21             JobKey jobKey = context.JobDetail.Key;22             if (isOpen("FrmConsole"))23             {24                 try25                 {26                     //获取当前Form1实例27                     __instance = (FrmConsole)Application.OpenForms["FrmConsole"];28                     // 如果任务是恢复的任务的话29                     if (context.Recovering)30                     {31                         __instance.SetInfo(string.Format("{0} RECOVERING at {1}", jobKey, DateTime.Now.ToString("r")));32                     }33                     else34                     {35                         __instance.SetInfo(string.Format("{0} starting at {1}", jobKey, DateTime.Now.ToString("r")));36                     }37 38                     JobDataMap data = context.JobDetail.JobDataMap;39                     int count;40                     if (data.ContainsKey(Count))41                     {42                         //是否能从数据库中恢复,如果保存Job等信息的话,程序运行突然终端(可用调试时中断运行,而不是关闭窗体来模拟)43                         count = data.GetInt(Count);44                     }45                     else46                     {47                         count = 0;48                     }49                     count++;50                     data.Put(Count, count);51 52                     __instance.SetInfo(string.Format(" {0} Count #{1}", jobKey, count));53                 }54                 catch (Exception ex)55                 {56                     Console.WriteLine(ex.Message);57                 }58             }59         }60 61 62         private static FrmConsole __instance = null;63 64         /// 65         /// 判断窗体是否打开66         /// 67         /// 68         /// 
69 private bool isOpen(string appName)70 {71 FormCollection collection = Application.OpenForms;72 foreach (Form form in collection)73 {74 if (form.Name == appName)75 {76 return true;77 }78 }79 return false;80 }81 82 }83 }

2 RecoveryStatefulJob

  是一个有状态的任务,和无状态的区别就是在任务类的上面用[PersistJobDataAfterExecution]标注任务是有状态的 , 有状态的任务不允许并发执行,也需要标注 [DisallowConcurrentExecution],代码如下:

1 using System; 2 using System.Collections.Specialized; 3 using System.Threading; 4 using Common.Logging; 5 using Quartz; 6 using Quartz.Impl; 7 using Quartz.Job; 8 using System.Windows.Forms; 9 namespace  QuartzDemo10 {11     /// 12     ///  用这个[PersistJobDataAfterExecution]标注任务是有状态的,13     ///  有状态的任务不允许并发执行 [DisallowConcurrentExecution]14     /// 15     [PersistJobDataAfterExecution]16     [DisallowConcurrentExecution]17     public class RecoveryStatefulJob : RecoveryJob18     {19 20     }21 }

3 AdoJobStoreExample

   用 properties["quartz.dataSource.default.connectionString"] = "Server=(local);Database=QRTZ_;Trusted_Connection=True;";定义了数据库的连接信息,程序运行时会自动将任务保存到数据库中:

1 using System;  2 using System.Collections.Specialized;  3 using System.Threading;  4 using Common.Logging;  5 using Quartz;  6 using Quartz.Impl;  7 using Quartz.Job;  8 using System.Windows.Forms;  9 namespace QuartzDemo 10 { 11     ///   12     ///  AdoJobStore的用法示例 13     ///  14     public class AdoJobStoreExample  15     { 16         public virtual void Run(bool inClearJobs, bool inScheduleJobs) 17         { 18             NameValueCollection properties = new NameValueCollection(); 19  20             properties["quartz.scheduler.instanceName"] = "TestScheduler"; 21             properties["quartz.scheduler.instanceId"] = "instance_one"; 22             properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz"; 23             properties["quartz.threadPool.threadCount"] = "5"; 24             properties["quartz.threadPool.threadPriority"] = "Normal"; 25             properties["quartz.jobStore.misfireThreshold"] = "60000"; 26             properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz"; 27             properties["quartz.jobStore.useProperties"] = "false"; 28             properties["quartz.jobStore.dataSource"] = "default"; 29             properties["quartz.jobStore.tablePrefix"] = "QRTZ_"; 30             properties["quartz.jobStore.clustered"] = "true"; 31             // SQLite 32             // properties["quartz.jobStore.lockHandler.type"] = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz"; 33             properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz"; 34     // 数据库连接字符串 35             properties["quartz.dataSource.default.connectionString"] = "Server=(local);Database=QRTZ_;Trusted_Connection=True;"; 36             properties["quartz.dataSource.default.provider"] = "SqlServer-20"; 37  38             // First we must get a reference to a scheduler 39             ISchedulerFactory sf = new StdSchedulerFactory(properties); 40             IScheduler sched = sf.GetScheduler(); 41  42             bool b是否恢复 = false; 43             if (inClearJobs) 44             { 45                Console.WriteLine("***** Deleting existing jobs/triggers *****"); 46                // sched.Clear(); 47             } 48  49           50             if (inScheduleJobs) 51             { 52               53                 string schedId = sched.SchedulerInstanceId; 54  55                 int count = 1; 56  57                 //定义一个无状态的任务 58                 IJobDetail job = JobBuilder.Create
() 59 .WithIdentity("recoveryjob_" + count, schedId) 60 .RequestRecovery() //recovery 61 .Build(); 62 63 64 ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create() 65 .WithIdentity("triger_" + count, schedId) 66 .StartAt(DateBuilder.FutureDate(1, IntervalUnit.Second)) 67 .WithSimpleSchedule(x => x.WithRepeatCount(20).WithInterval(TimeSpan.FromSeconds(3))) 68 .Build(); 69 //可用此来查看定义的触发器触发规则 70 //log.InfoFormat("{0} will run at: {1} and repeat: {2} times, every {3} seconds", 71 //job.Key, trigger.GetNextFireTimeUtc(), 72 //trigger.RepeatCount, 73 //trigger.RepeatInterval.TotalSeconds); 74 try 75 { 76 //如果数据库已经存在同名job和trigger,则绑定失败 77 sched.ScheduleJob(job, trigger); 78 } 79 catch 80 { 81 b是否恢复 = true; 82 } 83 count++; 84 85 //定义一个有状态的任务*********************************************************** 86 job = JobBuilder.Create
() 87 .WithIdentity("Statefuljob_" + count, schedId) 88 .RequestRecovery() // recovery 89 .Build(); 90 91 trigger = (ISimpleTrigger)TriggerBuilder.Create() 92 .WithIdentity("triger_" + count, schedId) 93 .StartAt(DateBuilder.FutureDate(1, IntervalUnit.Second)) 94 .WithSimpleSchedule(x => x.WithRepeatCount(20).WithInterval(TimeSpan.FromSeconds(3))) 95 .Build(); 96 97 try 98 { 99 sched.ScheduleJob(job, trigger);100 }101 catch102 {103 b是否恢复 = true;104 }105 106 107 108 }109 110 //启动111 sched.Start();112 //sched.Shutdown();113 114 }115 116 public string Name117 {118 get { return GetType().Name; }119 }120 121 public void Run()122 {123 bool clearJobs = true;124 //clearJobs = false;125 bool scheduleJobs = true;126 AdoJobStoreExample example = new AdoJobStoreExample();127 example.Run(clearJobs, scheduleJobs);128 }129 }130 }

 

  可以看到有状态的计数每次累加1,而无状态的每次执行时都会丢失累加数(新的实例),中断程序,查看数据库的QRTZ_JOB_DETAILS表,可以看见还有一个持久化的任务:

  中断程序后(调试状态时不关闭窗体,而是中断调试,模拟异常关闭) ,再重新运行可以看到如下界面:

 
 
转载:http://www.cnblogs.com/isaboy/p/Quartz_NET_stateful_job_adojobstore_sql_server.html

转载于:https://www.cnblogs.com/tianciliangen/p/8385240.html

你可能感兴趣的文章
Java 并发编程:volatile的使用及其原理
查看>>
[NOI2017]泳池
查看>>
HDU 1796 (容斥原理)
查看>>
merge-two-sorted-lists (归并排序中的合并)
查看>>
Android_清除/更新Bundle中的数据(不finish() Activity的情况下)
查看>>
ASP.NET对HTML元素进行权限控制(一)
查看>>
卷积神经网络Lenet-5实现-深入浅出
查看>>
Flex AdvancedDatagrid使用
查看>>
第一个pip安装包程序制作实验
查看>>
菏泽黑社会老大
查看>>
使用maven多模块来构建系统时,spring初始化报错的问题
查看>>
oracle内存粒度
查看>>
面向对象三大特性-继承
查看>>
C# 程序运行进度显示Lable
查看>>
495. 提莫攻击 Teemo Attacking
查看>>
374. 猜数字 Guess Number Higher or Lower
查看>>
微信公众平台开发教程第5篇-----网页授权获取用户基本信息
查看>>
mysql 与 sqlserver 的不同
查看>>
Codeforces 784B Santa Claus and Keyboard Check
查看>>
MySQL 表的一些操作
查看>>