亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Quartz.NET開源作業調度框架系列(五):AdoJobStore保存job到數據庫

2019-11-14 13:42:47
字體:
來源:轉載
供稿:網友

  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     /// <summary>12     /// 無狀態的可恢復的任務13     /// </summary>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         /// <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  QuartzDemo10 {11     /// <summary>12     ///  用這個[PersistJobDataAfterExecution]標注任務是有狀態的,13     ///  有狀態的任務不允許并發執行 [DisallowConcurrentExecution]14     /// </summary>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     /// <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             // 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<RecoveryJob>() 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<RecoveryStatefulJob>() 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表,可以看見還有一個持久化的任務:

  中斷程序后(調試狀態時不關閉窗體,而是中斷調試,模擬異常關閉) ,再重新運行可以看到如下界面:


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品日韩在线| 日韩大片在线观看视频| 成人黄色免费网站在线观看| 日韩在线观看成人| 久久久av电影| 日韩美女在线观看一区| 在线精品91av| 久久男人av资源网站| 亚洲欧美另类人妖| 国产精品久久久久99| 九九热在线精品视频| 国产男女猛烈无遮挡91| 在线亚洲男人天堂| 国产日韩精品一区二区| 久久久噜噜噜久久久| 亚洲欧洲美洲在线综合| 91av免费观看91av精品在线| 久久精品一偷一偷国产| 国产一区二区美女视频| 国产精品日韩欧美综合| 日韩在线欧美在线国产在线| 日韩电影在线观看永久视频免费网站| 午夜免费在线观看精品视频| 91精品91久久久久久| 国产精品成熟老女人| 8090理伦午夜在线电影| 色午夜这里只有精品| 亚洲一区国产精品| 91精品国产色综合久久不卡98口| 欧美噜噜久久久xxx| 中文字幕亚洲一区二区三区五十路| 亚洲人成在线一二| 91久久久精品| 欧美精品久久一区二区| 久久精品国产电影| 91在线高清免费观看| 大桥未久av一区二区三区| 久久精品视频播放| 国产精品女视频| 久久久久久久久综合| 日韩人体视频一二区| 色妞在线综合亚洲欧美| 色综合伊人色综合网站| 亚洲国产福利在线| 国产精品露脸av在线| 91美女高潮出水| 国产精品露脸自拍| 日韩成人激情影院| 午夜精品久久17c| 久久99久久亚洲国产| 欧美国产精品人人做人人爱| 日韩在线视频观看| 欧美伦理91i| 亚洲一区二区三区sesese| 91影视免费在线观看| 午夜免费在线观看精品视频| 国产一区二区三区在线观看视频| 日韩免费电影在线观看| 欧美日产国产成人免费图片| 亚洲精品av在线| 国产在线观看精品一区二区三区| 色综合伊人色综合网| 亚洲人成欧美中文字幕| 亚洲电影成人av99爱色| 欧美www视频在线观看| 久久天天躁日日躁| 久久久久久国产精品| 国产在线观看精品| 美女撒尿一区二区三区| 亚洲欧美制服第一页| 亚洲精品国产精品国产自| 欧美成人黄色小视频| 精品一区二区三区电影| 激情懂色av一区av二区av| 亚洲免费伊人电影在线观看av| 久久综合伊人77777尤物| 欧美大荫蒂xxx| 国产91露脸中文字幕在线| 日韩精品久久久久久久玫瑰园| 国产999视频| 国产精品www| 精品久久久久久久大神国产| 色无极亚洲影院| 日本精品视频在线| 91日本在线视频| 中文字幕亚洲天堂| 欧美性xxxxxx| 久久成年人免费电影| 日韩动漫免费观看电视剧高清| 亚洲大胆人体视频| 亚洲精品视频中文字幕| 97国产精品视频人人做人人爱| 日韩精品免费在线视频观看| 国产精品视频最多的网站| 色综合天天狠天天透天天伊人| 91精品国产综合久久香蕉的用户体验| 国产精品一区二区av影院萌芽| 国产精品av免费在线观看| 色av中文字幕一区| 亚洲在线观看视频| 亚洲日韩中文字幕在线播放| 日本中文字幕不卡免费| 91九色在线视频| 曰本色欧美视频在线| 国产精品女人网站| 性亚洲最疯狂xxxx高清| 国产精品羞羞答答| 国内精品久久久久久久| 97人人爽人人喊人人模波多| 国产在线视频91| 欧美刺激性大交免费视频| 2023亚洲男人天堂| 成人午夜激情免费视频| 国产视频丨精品|在线观看| 国产日韩在线精品av| 欧美小视频在线| 欧美成人精品在线观看| 欧美壮男野外gaytube| 久久色在线播放| 国产精品久久久一区| 米奇精品一区二区三区在线观看| 欧美日韩国产一中文字不卡| 国产日韩欧美视频在线| 日本中文字幕成人| 色香阁99久久精品久久久| 亚洲福利精品在线| 精品久久久久久亚洲国产300| 国产香蕉97碰碰久久人人| 精品视频在线播放色网色视频| 日韩欧美在线看| 成人黄色免费在线观看| 亚洲第一视频在线观看| 亚洲人成在线观| 日韩a**站在线观看| 一本大道香蕉久在线播放29| 亚洲成人免费在线视频| 欧美日韩国产中文字幕| 亚洲精品日产aⅴ| 2020欧美日韩在线视频| 欧美精品999| 国产精品一区久久久| 亚洲欧美中文字幕在线一区| 亚洲人午夜精品| 国产午夜精品久久久| 欧美黄色三级网站| 久久久精品久久久| 日本欧美精品在线| 成人午夜高潮视频| 欧美一区二区视频97| 伊人久久综合97精品| 久久久久久久久亚洲| 亚洲精品福利视频| 免费91麻豆精品国产自产在线观看| 一本大道久久加勒比香蕉| 中文字幕精品www乱入免费视频| 久久色免费在线视频| 精品国产一区二区三区四区在线观看| 欧美激情综合色| 黑人巨大精品欧美一区二区三区| 日韩激情片免费| 亚洲美女喷白浆| 在线观看视频亚洲| 欧美视频免费在线| 成人羞羞国产免费|