前面寫了關於Quartz.NET開源作業調度框架的入門和Cron Trigger , 這次繼續這個系列, 這次想討論一下Quartz.NET中的Job如何通過執行上下文(Execution Contex)進行參數傳遞 , 有些參數想保存狀態該如何處理 . 在Quartz.NET中可以用JobDataMap進行參數傳遞.本例用Quartz.NET的任務來定期輪詢數據庫表,當數據庫的條目達到一定的數目後,進行預警.(其實可以將讀取的表和預警條件配置到數據庫中的預警條件表中,這樣就可以簡單實現一個自動預警提醒的小平台).
1 using System; 2 using System.Threading; 3 4 using Common.Logging; 5 using Quartz; 6 using Quartz.Impl; 7 using Quartz.Job; 8 using Quartz.Impl.Calendar; 9 using Quartz.Impl.Matchers; 10 namespace QuartzDemo 11 { 12 13 public class JobWithParametersExample 14 { 15 public string Name 16 { 17 get { return GetType().Name; } 18 } 19 private IScheduler sched = null; 20 public JobWithParametersExample(IScheduler _sched) 21 { 22 sched = _sched; 23 } 24 public virtual void Run() 25 { 26 27 //2S後執行 28 DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(null, 2); 29 IJobDetail job1 = JobBuilder.Create<JobWithParameters>() 30 .WithIdentity("job1", "group1") 31 .Build(); 32 33 ISimpleTrigger trigger1 = (ISimpleTrigger)TriggerBuilder.Create() 34 .WithIdentity("trigger1", "group1") 35 .StartAt(startTime) 36 .WithSimpleSchedule(x => x.WithIntervalInSeconds(5).WithRepeatCount(100)) 37 .Build(); 38 39 // 設置初始參數 40 job1.JobDataMap.Put(JobWithParameters.tSQL, "SELECT * FROM [ACT_ID_USER]"); 41 job1.JobDataMap.Put(JobWithParameters.ExecutionCount, 1); 42 43 // 設置監聽器 44 JobListener listener = new JobListener(); 45 IMatcher<JobKey> matcher = KeyMatcher<JobKey>.KeyEquals(job1.Key); 46 sched.ListenerManager.AddJobListener(listener, matcher); 47 48 // 綁定trigger和job 49 sched.ScheduleJob(job1, trigger1); 50 //啟動 51 sched.Start(); 52 53 } 54 } 55 }
JobWithParametersExample用來配置job和trigger,同時定義了一個監聽器,來監聽定義的job.
1 using System; 2 using Common.Logging; 3 using Quartz; 4 using Quartz.Impl; 5 using Quartz.Job; 6 using System.Windows.Forms; 7 namespace QuartzDemo 8 { 9 10 [PersistJobDataAfterExecution] 11 [DisallowConcurrentExecution] 12 public class JobWithParameters : IJob 13 { 14 15 // 定義參數常量 16 public const string tSQL = "tSQL"; 17 public const string ExecutionCount = "count"; 18 public const string RowCount = "rowCount"; 19 public const string tableAlert = "tAlert"; 20 // Quartz 每次執行時都會重新實例化一個類, 因此Job類中的非靜態變量不能存儲狀態信息 21 private int counter = 1;//都為1 22 //private static int counter = 1;//可以保存狀態 23 public virtual void Execute(IJobExecutionContext context) 24 { 25 26 JobKey jobKey = context.JobDetail.Key; 27 // 獲取傳遞過來的參數 28 JobDataMap data = context.JobDetail.JobDataMap; 29 string SQL = data.GetString(tSQL); 30 int count = data.GetInt(ExecutionCount); 31 32 if (isOpen("FrmConsole")) 33 { 34 try 35 { 36 //獲取當前Form1實例 37 __instance = (FrmConsole)Application.OpenForms["FrmConsole"]; 38 //獲取當前執行的線程ID 39 __instance.SetInfo(jobKey + "Thread ID " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); 40 //數據庫操作 41 System.Data.DataTable tAlert = SqlHelper.getDateTable(SQL, null); 42 //回寫條數 43 data.Put(RowCount, tAlert.Rows.Count); 44 //通過方法更新消息 45 __instance.SetInfo(string.Format("{0} exec {1} = {2} get {3} rows\r\n execution count (from job map) is {4}\r\n execution count (from job member variable) is {5}", 46 jobKey, 47 tSQL, 48 SQL, 49 tAlert.Rows.Count, 50 count, counter)); 51 //怎麼取出Datatable ? json to datatable 52 //data.Put(tableAlert, tAlert); 53 } 54 catch (Exception ex) 55 { 56 Console.WriteLine(ex.Message); 57 } 58 } 59 // 修改執行計數並回寫到job data map中 60 count++; 61 data.Put(ExecutionCount, count); 62 // 修改本地變量,如果是非靜態變量,不能存儲狀態 63 counter++; 64 } 65 66 private static FrmConsole __instance = null; 67 68 /// <summary> 69 /// 判斷窗體是否打開 70 /// </summary> 71 /// <param name="appName"></param> 72 /// <returns></returns> 73 private bool isOpen(string appName) 74 { 75 FormCollection collection = Application.OpenForms; 76 foreach (Form form in collection) 77 { 78 if (form.Name == appName) 79 { 80 return true; 81 } 82 } 83 return false; 84 } 85 86 } 87 }
Quartz 每次執行時都會重新實例化一個類, 因此Job類中的非靜態變量不能存儲狀態信息.如何要保存狀態信息可以用靜態變量進行處理,也可以用參數值進行傳入傳出來實現.
1 using System; 2 using Common.Logging; 3 using Quartz; 4 using Quartz.Impl; 5 using Quartz.Job; 6 namespace QuartzDemo 7 { 8 public class JobListener : IJobListener 9 { 10 11 public virtual string Name 12 { 13 get { return "JobListener"; } 14 } 15 16 public virtual void JobToBeExecuted(IJobExecutionContext inContext) 17 { 18 //執行前執行 19 Console.WriteLine("JobToBeExecuted"); 20 } 21 22 public virtual void JobExecutionVetoed(IJobExecutionContext inContext) 23 { 24 //否決時執行 25 Console.WriteLine("JobExecutionVetoed"); 26 } 27 28 public virtual void JobWasExecuted(IJobExecutionContext inContext, JobExecutionException inException) 29 { 30 JobKey jobKey = inContext.JobDetail.Key; 31 // 獲取傳遞過來的參數 32 JobDataMap data = inContext.JobDetail.JobDataMap; 33 //獲取回傳的數據庫表條目數 34 int rowCount = data.GetInt(JobWithParameters.RowCount); 35 36 try 37 { 38 if (rowCount > 9) 39 { 40 inContext.Scheduler.PauseAll(); 41 System.Windows.Forms.MessageBox.Show("預警已超9條"); 42 inContext.Scheduler.ResumeAll(); 43 44 } 45 Console.WriteLine(rowCount.ToString()); 46 } 47 catch (SchedulerException e) 48 { 49 50 Console.Error.WriteLine(e.StackTrace); 51 } 52 } 53 54 } 55 }