前面写了关于Quartz.NET开源作业调度框架的入门和Cron Trigger , 这次继续这个系列, 这次想讨论一下Quartz.NET中的Job如何通过执行上下文(Execution Contex)进行参数传递 , 有些参数想保存状态该如何处理 。 在Quartz.NET中可以用JobDataMap进行参数传递。本例用Quartz.NET的任务来定期轮询数据库表,当数据库的条目达到一定的数目后,进行预警。(其实可以将读取的表和预警条件配置到数据库中的预警条件表中,这样就可以简单实现一个自动预警提醒的小平台)。
1 JobWithParametersExample
usingSystem; usingSystem.Threading; usingCommon.Logging; usingQuartz; usingQuartz.Impl; usingQuartz.Job; usingQuartz.Impl.Calendar; usingQuartz.Impl.Matchers; namespaceQuartzDemo{ publicclassJobWithParametersExample { publicstringName { get { returnGetType().Name; } } privateISchedulersched=null; publicJobWithParametersExample(IScheduler_sched) { sched=_sched; } publicvirtualvoidRun() { //2S后执行DateTimeOffsetstartTime=DateBuilder.NextGivenSecondDate(null, 2); IJobDetailjob1=JobBuilder.Create<JobWithParameters>() .WithIdentity("job1", "group1") .Build(); ISimpleTriggertrigger1= (ISimpleTrigger)TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .StartAt(startTime) .WithSimpleSchedule(x=>x.WithIntervalInSeconds(5).WithRepeatCount(100)) .Build(); // 设置初始参数job1.JobDataMap.Put(JobWithParameters.tSQL, "SELECT * FROM [ACT_ID_USER]"); job1.JobDataMap.Put(JobWithParameters.ExecutionCount, 1); // 设置监听器JobListenerlistener=newJobListener(); IMatcher<JobKey>matcher=KeyMatcher<JobKey>.KeyEquals(job1.Key); sched.ListenerManager.AddJobListener(listener, matcher); // 绑定trigger和jobsched.ScheduleJob(job1, trigger1); //启动sched.Start(); } } }
JobWithParametersExample用来配置job和trigger,同时定义了一个监听器,来监听定义的job.
2 JobWithParameters
usingSystem; usingCommon.Logging; usingQuartz; usingQuartz.Impl; usingQuartz.Job; usingSystem.Windows.Forms; namespaceQuartzDemo{ [PersistJobDataAfterExecution] [DisallowConcurrentExecution] publicclassJobWithParameters : IJob { // 定义参数常量publicconststringtSQL="tSQL"; publicconststringExecutionCount="count"; publicconststringRowCount="rowCount"; publicconststringtableAlert="tAlert"; // Quartz 每次执行时都会重新实例化一个类, 因此Job类中的非静态变量不能存储状态信息privateintcounter=1;//都为1//private static int counter = 1;//可以保存状态publicvirtualvoidExecute(IJobExecutionContextcontext) { JobKeyjobKey=context.JobDetail.Key; // 获取传递过来的参数JobDataMapdata=context.JobDetail.JobDataMap; stringSQL=data.GetString(tSQL); intcount=data.GetInt(ExecutionCount); if (isOpen("FrmConsole")) { try { //获取当前Form1实例__instance= (FrmConsole)Application.OpenForms["FrmConsole"]; //获取当前执行的线程ID__instance.SetInfo(jobKey+"Thread ID "+System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); //数据库操作System.Data.DataTabletAlert=SqlHelper.getDateTable(SQL, null); //回写条数data.Put(RowCount, tAlert.Rows.Count); //通过方法更新消息__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}", jobKey, tSQL, SQL, tAlert.Rows.Count, count, counter)); //怎么取出Datatable ? json to datatable//data.Put(tableAlert, tAlert); } catch (Exceptionex) { Console.WriteLine(ex.Message); } } // 修改执行计数并回写到job data map中count++; data.Put(ExecutionCount, count); // 修改本地变量,如果是非静态变量,不能存储状态counter++; } privatestaticFrmConsole__instance=null; /// <summary>/// 判断窗体是否打开/// </summary>/// <param name="appName"></param>/// <returns></returns>privateboolisOpen(stringappName) { FormCollectioncollection=Application.OpenForms; foreach (Formformincollection) { if (form.Name==appName) { returntrue; } } returnfalse; } } }
Quartz 每次执行时都会重新实例化一个类, 因此Job类中的非静态变量不能存储状态信息.如何要保存状态信息可以用静态变量进行处理,也可以用参数值进行传入传出来实现。
3 JobListener
下面通过实现一个接口IJobListener来完成监听器,其中包含任务执行前、执行中和执行后的方法,可以在对应方法中根据业务场景来进行定制,相关示例如下所示:
usingSystem; usingCommon.Logging; usingQuartz; usingQuartz.Impl; usingQuartz.Job; namespaceQuartzDemo{ publicclassJobListener : IJobListener { publicvirtualstringName { get { return"JobListener"; } } publicvirtualvoidJobToBeExecuted(IJobExecutionContextinContext) { //执行前执行Console.WriteLine("JobToBeExecuted"); } publicvirtualvoidJobExecutionVetoed(IJobExecutionContextinContext) { //否决时执行Console.WriteLine("JobExecutionVetoed"); } publicvirtualvoidJobWasExecuted(IJobExecutionContextinContext, JobExecutionExceptioninException) { JobKeyjobKey=inContext.JobDetail.Key; // 获取传递过来的参数JobDataMapdata=inContext.JobDetail.JobDataMap; //获取回传的数据库表条目数introwCount=data.GetInt(JobWithParameters.RowCount); try { if (rowCount>9) { inContext.Scheduler.PauseAll(); System.Windows.Forms.MessageBox.Show("预警已超9条"); inContext.Scheduler.ResumeAll(); } Console.WriteLine(rowCount.ToString()); } catch (SchedulerExceptione) { Console.Error.WriteLine(e.StackTrace); } } } }
4 效果
执行此示例,修改相关的数据,预警规则定期执行,则巡检数据,如有符合预警的数据,则进行预警。具体如下图所示: