如果在Quartz.NET作業運作時我們想動态修改Job和Trigger的綁定關系,同時修改一些參數那麼該怎麼辦呢?Quartz.NET提供了插件技術,可以通過在XML檔案中對Job和Trigger的參數進行配置,然後定期去加載配置檔案來執行個體化任務和Trigger,這樣就解決了此類問題。
1 PlugInJobExample
下面給出一個示例程式,用插件XML定義的propertie來執行個體化一個ISchedulerFactory,配置檔案名稱用properties["quartz.plugin.jobInitializer.fileNames"] = "quartz_jobs.xml";語句來進行限定。具體示例代碼如下:
using System;
using System.Collections.Specialized;
using System.Threading;
using Common.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Job;
using System.Windows.Forms;
namespace QuartzDemo
{
public class PlugInJobExample
{
public string Name
{
get { return GetType().Name; }
}
public virtual IScheduler Run()
{
var properties = new NameValueCollection();
properties["quartz.plugin.triggHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin";
properties["quartz.plugin.jobInitializer.type"] = "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin";
//配置檔案名稱
properties["quartz.plugin.jobInitializer.fileNames"] = "quartz_jobs.xml";
properties["quartz.plugin.jobInitializer.failOnFileNotFound"] = "true";
//每隔120秒進行探查,看配置檔案是否更改
properties["quartz.plugin.jobInitializer.scanInterval"] = "120";
// 用插件XML定義的propertie來執行個體化一個ISchedulerFactory
ISchedulerFactory sf = new StdSchedulerFactory(properties);
IScheduler sched = sf.GetScheduler();
//啟動
sched.Start();
//傳回
return sched;
}
}
}
2 SimpleJob1
下面給出一個簡單的Job定義,它實作了IJob接口,這裡需要實作Execute(IJobExecutionContext context)方法,它可以更新另外一個視窗的相關資訊。示例代碼如下:
using System;
using System.Collections.Generic;
using Common.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Job;
using System.Windows.Forms;
namespace QuartzDemo
{
public class SimpleJob1 : IJob
{
public virtual void Execute(IJobExecutionContext context)
{
JobKey jobKey = context.JobDetail.Key;
if (isOpen("FrmConsole"))
{
try
{
//擷取目前Form1執行個體
__instance = (FrmConsole)Application.OpenForms["FrmConsole"];
//擷取目前執行的線程ID
__instance.SetInfo(" - "+jobKey + "Thread ID " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());
//通過方法更新消息
__instance.SetInfo(string.Format(" - {0} exec at {1}",
jobKey,
System.DateTime.Now.ToString()));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
// This job simply prints out its job name and the
if (context.MergedJobDataMap.Count > 0)
{
ICollection<string> keys = context.MergedJobDataMap.Keys;
foreach (string key in keys)
{
String val = context.MergedJobDataMap.GetString(key);
__instance.SetInfo(string.Format(" - MergedJobDataMap entry: {0} = {1}", key, val));
}
}
context.Result = "exec ok";
}
private static FrmConsole __instance = null;
/// <summary>
/// 判斷窗體是否打開
/// </summary>
/// <param name="appName"></param>
/// <returns></returns>
private bool isOpen(string appName)
{
FormCollection collection = Application.OpenForms;
foreach (Form form in collection)
{
if (form.Name == appName)
{
return true;
}
}
return false;
}
}
}
3 xml配置檔案
下面第一個是簡單的Trigger配置,<repeat-interval>1000</repeat-interval>表示間隔時間為1秒,<repeat-count>100</repeat-count>表示循環次數為100次。第二個用的是CronTrigger進行任務定義,周期使用CronExpression進行限定的,如<cron-expression>0/2 * * * * ?</cron-expression>。相關示例代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">
<processing-directives>
<overwrite-existing-data>true</overwrite-existing-data>
</processing-directives>
<schedule>
<job>
<name>jobName1</name>
<group>jobGroup1</group>
<description>jobDesciption1</description>
<job-type>QuartzDemo.SimpleJob1, QuartzDemo</job-type>
<durable>true</durable>
<recover>false</recover>
<job-data-map>
<entry>
<key>key0</key>
<value>value0</value>
</entry>
<entry>
<key>key1</key>
<value>value1</value>
</entry>
<entry>
<key>key2</key>
<value>value2</value>
</entry>
</job-data-map>
</job>
<trigger>
<simple>
<name>simpleName</name>
<group>simpleGroup</group>
<description>SimpleTriggerDescription</description>
<job-name>jobName1</job-name>
<job-group>jobGroup1</job-group>
<start-time>2015-12-02T10:15:00.0Z</start-time>
<end-time>2020-05-04T18:13:51.0Z</end-time>
<misfire-instruction>SmartPolicy</misfire-instruction>
<repeat-count>100</repeat-count>
<repeat-interval>1000</repeat-interval>
</simple>
</trigger>
</schedule>
</job-scheduling-data>
<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">
<processing-directives>
<overwrite-existing-data>true</overwrite-existing-data>
</processing-directives>
<schedule>
<job>
<name>SimpleJob1</name>
<group>myJobGroup1</group>
<description>SimpleJob1</description>
<job-type>QuartzDemo.SimpleJob1, QuartzDemo</job-type>
<durable>true</durable>
<recover>false</recover>
<job-data-map>
<entry>
<key>author</key>
<value>jackwangcumt</value>
</entry>
<entry>
<key>blog</key>
<value>isaboy</value>
</entry>
<entry>
<key>jobType</key>
<value>XML Plugin Job</value>
</entry>
</job-data-map>
</job>
<trigger>
<cron>
<name>trigger1</name>
<group>myTriggerGroup</group>
<job-name>SimpleJob1</job-name>
<job-group>myJobGroup1</job-group>
<cron-expression>0/2 * * * * ?</cron-expression>
</cron>
</trigger>
</schedule>
</job-scheduling-data>
4 效果
執行示例程式,界面如下:

可以通過修改配置檔案,動态修改任務的相關參數,示範動畫如下圖所示: