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  QuartzDemo
10 {
11     /// <summary>
12     /// 无状态的可恢复的任务
13     /// </summary>
14     public class RecoveryJob : IJob
15     {
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                 try
25                 {
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                     else
34                     {
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                     else
46                     {
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         /// <summary>
65         /// 判断窗体是否打开
66         /// </summary>
67         /// <param name="appName"></param>
68         /// <returns></returns>
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  QuartzDemo
10 {
11     /// <summary>
12     ///  用这个[PersistJobDataAfterExecution]标注任务是有状态的,
13     ///  有状态的任务不允许并发执行 [DisallowConcurrentExecution]
14     /// </summary>
15     [PersistJobDataAfterExecution]
16     [DisallowConcurrentExecution]
17     public class RecoveryStatefulJob : RecoveryJob
18     {
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 QuartzDemo10 {11     /// <summary> 12     ///  AdoJobStore的用法示例13     /// </summary>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             // SQLite32             // 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 scheduler39             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<RecoveryJob>()59                     .WithIdentity("recoveryjob_" + count, schedId) 60                     .RequestRecovery() //recovery61                     .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                 try75                 {76                     //如果数据库已经存在同名job和trigger,则绑定失败77                     sched.ScheduleJob(job, trigger);78                 }79                 catch80                 {81                     b是否恢复 = true;82                 }83                 count++;84 85                 //定义一个有状态的任务***********************************************************86                 job = JobBuilder.Create<RecoveryStatefulJob>()87                     .WithIdentity("Statefuljob_" + count, schedId)88                     .RequestRecovery() // recovery89                     .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                 try98                 {99                     sched.ScheduleJob(job, trigger);
100                 }
101                 catch
102                 {
103                     b是否恢复 = true;
104                 }
105
106
107
108             }
109
110             //启动
111             sched.Start();
112             //sched.Shutdown();
113
114         }
115
116         public string Name
117         {
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

Quartz.NET开源作业调度框架系列(五):AdoJobStore保存job到数据库相关推荐

  1. Quartz.NET开源作业调度框架系列(二):CronTrigger-转

    CronTriggers比SimpleTrigger更加的灵活和有用,对于比较复杂的任务触发规则,例如"每个星期天的晚上12:00"进行备份任务,SimpleTrigger就不能胜 ...

  2. .NET开源作业调度框架Quartz

    .NET开源作业调度框架Quartz 一 Quartz简介 Quartz是一个强大.开源.轻量的作业调度框架,你能够用它来为执行一个简单或复杂的作业调度任务. 是对非常流行的JAVA开源调度框架 Qu ...

  3. .Net平台开源作业调度框架Quartz.Net

    Quartz.NET介绍: Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中. ...

  4. 开发一款开源爬虫框架系列(五):爬虫架构的一些新思路

    爬虫开源项目地址:http://git.oschina.net/coliza/MongooCrawler 以前的思路是由客户端完成所有的下载网页,解析等功能,服务器端负责从内存队列中拿到数据并将获取的 ...

  5. 【Python】Flask框架系列(四):Flask-Migrate数据库迁移

    参考:flask数据库迁移理解及命令 Flask-Migrate 使用数据库迁移,可以直接建表,而不用我们自己写sql语句用来建表.就是将关系型数据库的一张张表转化成了Python的一个个类. 在开发 ...

  6. quartz cron 每周一_quartz框架和关闭超时订单

    Quartz Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.Quartz可以用来创建简单或为运 ...

  7. Quartz.NET实现作业调度

    一.Quartz.NET介绍 Quartz.NET是一个强大.开源.轻量的作业调度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改写,可用于winform和asp ...

  8. 作业调度框架_Quartz

    什么是Quartz Quartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制.Quartz允许开发人员根据时间间隔来调度作业.它实现了作业和触发 ...

  9. 从零开始搭建Android框架系列

    原文链接:http://www.jianshu.com/nb/3767449 开篇介绍和工程目录结构[从零开始搭建android框架系列(1)] 不容错过,最全的安卓架构合集[从零开始搭建androi ...

  10. Quartz作业调度框架

    Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度.本 ...

最新文章

  1. 不会跳回到微博认定申请书
  2. 详解Go语言的计时器
  3. Libbpf-tools: Tracing工具
  4. DSB2017第一名代码尝试运行(记录自用)(五)
  5. Navicat 连接 Oracle数据库并,导入数据泵(.dmp)
  6. python docx 表格_python-docx表格添加和删除数据
  7. Maya中操作普通DG节点和Dag节点的区别
  8. 算法面试题:均分纸牌
  9. expert php and mysql_Expert PHP and Mysql
  10. servlet跳转问题
  11. [循证理论与实践] meta分析系列之二: meta分析的软件
  12. 给大家推荐下这几年看过的觉得不错的视频教程
  13. HOJ 2706 Key Task
  14. 报错Takes no arguements解决办法
  15. text-decoration下划线 删除线 上划线属性样式
  16. stm32 mbed 入门教程(一)---前期准备
  17. 搭建微信小游戏开发环境总结
  18. 基于单片机的智能小区安防系统的设计
  19. 【沙发管家】夏普电视怎么装软件?怎么才能看免费电影,电视直播?
  20. Python 计算思维训练——输入和错误处理练习(一)

热门文章

  1. 苹果Mac 2D/3D数字雕刻软件:Pixologic Zbrush
  2. 文字转语音功能,MacOS只需两行代码
  3. SpringBoot 实战 (二) | 第一个 SpringBoot 工程详解
  4. gatsbyjs 了解
  5. 云端模糊测试挖洞实例
  6. CSS-----盒子模型
  7. C# WinForm 使用FlowLayoutPanel控件做为导航菜单按钮的容器
  8. 快速备份和还原 MySQL 数据库的另一种方法
  9. jQery动态添加删除类样式
  10. android 获取屏幕宽高