麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Quartz.NET開(kāi)源作業(yè)調(diào)度框架系列(五):AdoJobStore保存job到數(shù)據(jù)庫(kù)

2019-11-14 13:42:47
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  Quartz.NET 任務(wù)調(diào)度的核心元素是 scheduler, trigger 和 job,其中 trigger(用于定義調(diào)度時(shí)間的元素,即按照什么時(shí)間規(guī)則去執(zhí)行任務(wù)) 和 job 是任務(wù)調(diào)度的元數(shù)據(jù),scheduler 是實(shí)際執(zhí)行調(diào)度的控制器。在Quartz.NET中主要有兩種類(lèi)型的 job:無(wú)狀態(tài)的(stateless)和有狀態(tài)的(stateful)。對(duì)于同一個(gè) trigger 來(lái)說(shuō),有狀態(tài)的 job 不能被并行執(zhí)行,只有上一次觸發(fā)的任務(wù)被執(zhí)行完之后,才能觸發(fā)下一次執(zhí)行。無(wú)狀態(tài)任務(wù)一般指可以并發(fā)的任務(wù),即任務(wù)之間是獨(dú)立的,不會(huì)互相干擾。一個(gè) job 可以被多個(gè) trigger 關(guān)聯(lián),但是一個(gè) trigger 只能關(guān)聯(lián)一個(gè) job。某些任務(wù)需要對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行增刪改處理 , 這些任務(wù)不能并發(fā)執(zhí)行,就需要用到無(wú)狀態(tài)的任務(wù) , 否則會(huì)造成數(shù)據(jù)混亂。

  另外有些情況下,我們需要將任務(wù)保存到數(shù)據(jù)庫(kù)中,特別是有些任務(wù)中包含參數(shù),例如累加的任務(wù),如果可以保存到數(shù)據(jù)庫(kù)中,即便中間斷電或者程序異常重啟,中間計(jì)算的結(jié)果也不會(huì)丟失,可以從斷點(diǎn)的結(jié)果進(jìn)行運(yùn)算(首先恢復(fù)任務(wù)),下面介紹一下如何用AdoJobStore將任務(wù)保存到SQL Server數(shù)據(jù)庫(kù)中. 

  事先要在數(shù)據(jù)庫(kù)上新建一個(gè)QRTZ_數(shù)據(jù)庫(kù),并執(zhí)行SQL建表腳本:

1 RecoveryJob

  是一個(gè)無(wú)狀態(tài)的任務(wù),代碼如下:

 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     /// 無(wú)狀態(tài)的可恢復(fù)的任務(wù)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                     //獲取當(dāng)前Form1實(shí)例27                     __instance = (FrmConsole)application.OpenForms["FrmConsole"];28                     // 如果任務(wù)是恢復(fù)的任務(wù)的話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                         //是否能從數(shù)據(jù)庫(kù)中恢復(fù),如果保存Job等信息的話,程序運(yùn)行突然終端(可用調(diào)試時(shí)中斷運(yùn)行,而不是關(guān)閉窗體來(lái)模擬)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         /// 判斷窗體是否打開(kāi)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

  是一個(gè)有狀態(tài)的任務(wù),和無(wú)狀態(tài)的區(qū)別就是在任務(wù)類(lèi)的上面用[PersistJobDataAfterExecution]標(biāo)注任務(wù)是有狀態(tài)的 , 有狀態(tài)的任務(wù)不允許并發(fā)執(zhí)行,也需要標(biāo)注 [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     ///  用這個(gè)[PersistJobDataAfterExecution]標(biāo)注任務(wù)是有狀態(tài)的,13     ///  有狀態(tài)的任務(wù)不允許并發(fā)執(zhí)行 [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;";定義了數(shù)據(jù)庫(kù)的連接信息,程序運(yùn)行時(shí)會(huì)自動(dòng)將任務(wù)保存到數(shù)據(jù)庫(kù)中:

  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     // 數(shù)據(jù)庫(kù)連接字符串 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是否恢復(fù) = 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                 //定義一個(gè)無(wú)狀態(tài)的任務(wù) 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                 //可用此來(lái)查看定義的觸發(fā)器觸發(fā)規(guī)則 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                     //如果數(shù)據(jù)庫(kù)已經(jīng)存在同名job和trigger,則綁定失敗 77                     sched.ScheduleJob(job, trigger); 78                 } 79                 catch 80                 { 81                     b是否恢復(fù) = true; 82                 } 83                 count++; 84  85                 //定義一個(gè)有狀態(tài)的任務(wù)*********************************************************** 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是否恢復(fù) = true;104                 }105 106 107                108             }109         110             //啟動(dòng)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 }

 

  可以看到有狀態(tài)的計(jì)數(shù)每次累加1,而無(wú)狀態(tài)的每次執(zhí)行時(shí)都會(huì)丟失累加數(shù)(新的實(shí)例),中斷程序,查看數(shù)據(jù)庫(kù)的QRTZ_JOB_DETAILS表,可以看見(jiàn)還有一個(gè)持久化的任務(wù):

  中斷程序后(調(diào)試狀態(tài)時(shí)不關(guān)閉窗體,而是中斷調(diào)試,模擬異常關(guān)閉) ,再重新運(yùn)行可以看到如下界面:


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 色999久久久精品人人澡69 | 在线观看免费污视频 | 久久亚洲精选 | 欧美一级黄色免费看 | 久久丝袜脚交足黄网站免费 | 国产电影精品久久 | 国产亚洲美女精品久久久2020 | 免费欧美一级视频 | 欧美视频在线一区二区三区 | 国产精品麻豆一区二区三区 | 色97在线 | 国产亚洲网 | 国产成人自拍av | 久久国产精品区 | 一级毛片真人免费播放视频 | 国产一区二区二 | 黄wwww | 色综合久久久久综合99 | 国产福利视频在线观看 | 久久久久久久91 | 玖草| 久久av一区二区 | 欧美在线 | 亚洲 | 精品一区二区电影 | 国产精品久久久久久久娇妻 | 成人在线视频网 | 日日狠狠久久偷偷四色综合免费 | 一本色道久久久888 国产一国产精品一级毛片 国产精品高潮视频 | 麻豆一区二区99久久久久 | 久久精品一区二区三区四区五区 | www.91sese| 国产精品一区在线免费观看 | 一级毛片播放 | 国产精品99久久99久久久二 | 伊人在线视频 | 免费黄色大片在线观看 | 舌头伸进添的我好爽高潮网站 | hdhdhd79xxxxх | 爱高潮www亚洲精品 国产精品一区自拍 | 亚洲成人中文字幕在线 | 国产羞羞视频 |