天天看點

Quartz.NET開源作業排程架構系列(一):快速入門step by step

  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.NET開源作業排程架構系列(一):快速入門step by step

 Quartz依賴庫為Common.Logging和Common.Logging.Core  ,  二者需要一并導入 . 然後修改Form1的标題為QuartzDemo.

2.2 Form1定制

  在Form1設計視圖上 , 為該窗體添加一個TextBox和Panel , 并設定相關屬性(背景色,字型等) , 如下圖所示:

Quartz.NET開源作業排程架構系列(一):快速入門step by step

  為了直覺的執行定期任務 , 我們添加一個時序圖(用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"));
}      
Quartz.NET開源作業排程架構系列(一):快速入門step by step

3 最終效果

   最終效果如下 , 每隔1秒,就是用随機的數來更新文本框和圖表中的内容:

Quartz.NET開源作業排程架構系列(一):快速入門step by step

值得注意的是,如果用下面的代碼格式,必須保證二者的名稱完全一緻,否則無法實作任務和觸發器的綁定.

Quartz.NET開源作業排程架構系列(一):快速入門step by step