Quartz.NET是一個被廣泛使用的開源作業排程架構 , 由于是用C#語言建立,可友善的用于winform和asp.net應用程式中。Quartz.NET提供了巨大的靈活性但又兼具簡單性。開發人員可用它快捷的建立并執行一個自動化作業。Quartz.NET有很多特征,如:資料庫支援,叢集,插件,支援cron-like表達式等。
1 為什麼選擇Quartz.NET
在大部分的應用中,都需要對資料庫進行定期備份 , 這個備份任務可以是每天晚上12:00或者每周星期二晚上12:00,或許僅僅每個月的最後一天執行。如果應用程式中需要這樣的自動化執行任務 , 那麼建議使用Quartz.NET排程器作為架構,為我們提供基礎服務。 Quartz.NET允許開發人員根據時間間隔(或天)來排程作業 , 它實作了作業和觸發器的多對多關系,還能把多個作業與不同的觸發器關聯。整合了 Quartz.NET的應用程式可以重用來自不同僚件的作業,還可以為一個事件組合多個作業.
2 如何建立一個簡單的Quartz.NET
2.1 建立桌面應用程式并添加類庫
用VS2012建立一個QuartzDemo的桌面應用程式 , 并用NuGet程式包管理添加Quartz.NET , 添加好類庫後 , 項目檔案如下圖所示:

Quartz依賴庫為Common.Logging和Common.Logging.Core , 二者需要一并導入 . 然後修改Form1的标題為QuartzDemo.
2.2 Form1定制
在Form1設計視圖上 , 為該窗體添加一個TextBox和Panel , 并設定相關屬性(背景色,字型等) , 如下圖所示:
為了直覺的執行定期任務 , 我們添加一個時序圖(用Oxyplot控件) , 這裡下載下傳并引用Oxyplot.在Form1.cs檔案中 ,首先引入需要的命名空間:
using Quartz;
using Quartz.Impl;
using Quartz.Job;
using System.Threading;
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
重載一個帶參數的Form1構造方法:
private bool isFirst = true;
public Form1(string msg)
{
InitializeComponent();
_msg = msg;
try
{
//啟動 scheduler
scheduler.Start();
// 定義一個job并和自定義的HelloJob進行綁定
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("HelloJob", "SimpleGroup")
.Build();
#region Cron Expressions
// ITrigger trigger2 = TriggerBuilder.Create()
//.WithIdentity("trigger3", "group1")
//.WithCronSchedule(" 0 0/5 * * * ?", x => x
// .WithMisfireHandlingInstructionFireAndProceed())
//.ForJob("job1", "group1")
//.Build();
#endregion
//定義一個即時觸發的觸發器,(每隔1秒進行重複執行)
ITrigger trigger= TriggerBuilder.Create()
.WithIdentity("trigger1", "SimpleGroup")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(1)
.RepeatForever())
.Build();
// 将job和trigger進行綁定,并告知 quartz 排程器用trigger去執行job
scheduler.ScheduleJob(job, trigger);
}
catch (SchedulerException se)
{
Console.WriteLine(se);
}
}
在Form1的FormClosed事件,即窗體關閉後,将scheduler關閉:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//關閉 scheduler
scheduler.Shutdown();
}
在窗體加載時,建立一個時序圖:
public OxyPlot.WindowsForms.PlotView Plot;
private LineSeries lineSeries = new LineSeries { Title = "即時監控(1秒)", StrokeThickness =2 };
private void Form1_Load(object sender, EventArgs e)
{
Plot = new OxyPlot.WindowsForms.PlotView();
Plot.Model = new PlotModel();
Plot.Dock = DockStyle.Fill;
this.panel1.Controls.Add(Plot);
Plot.Model.PlotType = PlotType.XY;
Plot.Model.Background = OxyColor.FromRgb(255, 255, 255);
Plot.Model.TextColor = OxyColor.FromRgb(0, 0, 0);
// add Series and Axis to plot model
Plot.Model.Series.Add(lineSeries);
Plot.Model.Axes.Add(new LinearAxis());
}
定義一個SetMsg方法來更新消息:
private double xInit = 0;
public bool SetMsg(string msg)
{
_msg = msg;
//号稱NET4最簡單的跨程序更新UI的方法
this.Invoke((MethodInvoker)delegate
{
// runs on UI thread
if (isFirst)
{
this.txtLog.AppendText("Hello to Quartz NET ! Created by JackWang 2015");
isFirst = false;
}
this.txtLog.AppendText(string.Format("\r\n$JackWang>> You get {0} message from Quartz MyJob...", _msg));
xInit = xInit + 1;
lineSeries.Points.Add(new DataPoint(xInit,double.Parse(_msg)));
if (lineSeries.Points.Count > 50)
{
//保留最近50個點
lineSeries.Points.RemoveAt(0);
}
//更新圖表資料
this.Plot.Model.InvalidatePlot(true);
});
return true;
}
2.3 定義一個HelloJob
在帶參數的Form1構造方法中 , 建立的HelloJob的定義為:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace QuartzDemo
{
using Quartz;
using Quartz.Impl;
using Quartz.Job;
public class HelloJob : IJob
{
private static Form1 __instance = null;
public void Execute(IJobExecutionContext context)
{
if (isOpen("Form1"))
{
//擷取目前Form1執行個體
__instance = (Form1)Application.OpenForms["Form1"];
//随機生成小于100的數
string num = new Random().Next(100).ToString();
//通過方法更新消息
__instance.SetMsg(num);
}
else
{
//__instance = new Form1("0");
//__instance.Show();
}
}
/// <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;
}
}
}
注意修改Program.cs中用帶參數的Form1建構方法進行執行個體建立:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1("0"));
}
3 最終效果
最終效果如下 , 每隔1秒,就是用随機的數來更新文本框和圖表中的内容:
值得注意的是,如果用下面的代碼格式,必須保證二者的名稱完全一緻,否則無法實作任務和觸發器的綁定.