正如標題所示,文章主要是圍繞Quartz.Net做業調度框架話題展開的,內容出自博主學習官方Examples的學習心得與體會,文中不免會有錯誤之處,還請指出得以指教。html
在百度一下搜索Quartz.Net,能夠知道Quartz.Net是Net版本的任務調度框架,是一個從java移植過來的Net版本的開源框架,在做業調度方面提供了很好的靈活性而不犧牲簡單,可以爲執行一個做業而建立簡單的或複雜的調度,目前版本支持數據庫,集羣,插件配置,支持cron表達式等等java
Quartz Enterprise Schedulder .Netweb
官方下載地址:數據庫
http://sourceforge.net/projects/quartznet/files/quartznet/框架
官方文檔:ide
http://www.quartz-scheduler.net/documentation/index.html函數
到此咱們大概瞭解了一下Quartz.Net是什麼,在繼續討論相關Quartz以前,咱們先來思考並解決一個問題。學習
假設程序有這麼一個需求,在必定的時間間隔裏,輪詢作一種操做或者任務,我想首先固然能夠這麼實現:ui
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestConsole { class Program { static void Main(string[] args) { Process(); } public static void Process() { DateTime now = DateTime.Now; //1.0 讀取web.config中的定時器的時間間隔 string timespan = System.Configuration.ConfigurationManager.AppSettings["timer"]; double dtimespan = 0; int repeat = 0; if (double.TryParse(timespan, out dtimespan) == false) { dtimespan = 10; } Console.WriteLine("Info[{0}]任務初始化完成.....",DateTime.Now); while (true) { try { //1.0 開啓定時器 if ((DateTime.Now - now).TotalSeconds >= dtimespan) { Console.WriteLine("任務正在執行.....這是第{0}次",repeat+1); //開始調度任務 SayHello(); repeat++; Console.WriteLine("任務執行完成....."); //重置now now = DateTime.Now; } //預留cpu的線程切換時間 System.Threading.Thread.Sleep(2000); } catch (Exception ex) { Console.WriteLine("Error:{0}",ex.ToString()); } } } public static void SayHello() { Console.WriteLine("Info:[{0}] Hello, everyone, I'm YZR.",DateTime.Now); } } }
運行的結果以下:spa
Info[2016/4/23 星期六 上午 12:01:57]任務初始化完成.....
任務正在執行.....這是第1次
Info:[2016/4/23 星期六 上午 12:02:17] Hello, everyone, I'm YZR.
任務執行完成.....
任務正在執行.....這是第2次
Info:[2016/4/23 星期六 上午 12:02:37] Hello, everyone, I'm YZR.
任務執行完成.....
任務正在執行.....這是第3次
Info:[2016/4/23 星期六 上午 12:02:57] Hello, everyone, I'm YZR.
任務執行完成.....
任務正在執行.....這是第4次
Info:[2016/4/23 星期六 上午 12:03:17] Hello, everyone, I'm YZR.
任務執行完成.....
上面的程序完成的功能是每20秒會在控制檯中打印SayHello的信息,而且會記錄任務重複執行的次數。
其實這就是一個簡單的任務調度的過程,接下來演示使用Quartz.Net如何實現這個功能:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Common.Logging; namespace Quartz.Examples { public class SayHelloJob : IJob { private static ILog _log = LogManager.GetLogger(typeof(HelloJob)); /// <summary> /// 做業或者任務須要一個無參構造函數來進行初始化 /// </summary> public SayHelloJob() { } #region IJob 成員 public void Execute(IJobExecutionContext context) { _log.Info(string.Format("Hello, everyone, I'm YZR. - {0}", System.DateTime.Now.ToString("r"))); } #endregion } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using Quartz.Impl; using Common.Logging; namespace Quartz.Examples { public class SayHelloExample:IExample { #region IExample 成員 public string Name { get { return GetType().Name; } } public void Run() { ILog log = LogManager.GetLogger(typeof(SimpleExample)); log.Info("------- 初始化中 ----------------------"); //首先,咱們必須獲得一個參考的調度程序 ISchedulerFactory sf = new StdSchedulerFactory(); IScheduler sched = sf.GetScheduler(); log.Info("------- 初始化完成 -----------"); // 獲得一個輪詢的觸發時間 DateTimeOffset runTime = DateBuilder.EvenMinuteDate(DateTimeOffset.UtcNow); log.Info("------- 調度做業 -------------------"); // 定義一個做業而且綁定到指定的Job類中 IJobDetail job = JobBuilder.Create<SayHelloJob>() .WithIdentity("job1", "group1") .Build(); // 做業的觸發器會在下一次輪詢的時機中執行做業 ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .StartAt(runTime).WithSimpleSchedule(x=>x.WithIntervalInSeconds(20).RepeatForever()) .Build(); //根據做業和觸發器添加到調度隊列 sched.ScheduleJob(job, trigger); log.Info(string.Format("{0} will run at: {1}", job.Key, runTime.ToString("r"))); //啓動調度程序 sched.Start(); log.Info("------- 開始調度 -----------------"); log.Info("------- 等待2分鐘.... -------------"); //睡眠65秒 Thread.Sleep(TimeSpan.FromSeconds(120)); // shut down the scheduler log.Info("------- 正在關閉調度做業 ---------------------"); sched.Shutdown(true); log.Info("------- 關閉調度做業完成 -----------------"); } #endregion } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Quartz.Util; using System.Reflection; namespace Quartz.Examples { class Program { static void Main(string[] args) { try { //反射獲得當前運行程序集 Assembly asm = Assembly.GetExecutingAssembly(); //獲取全部類 Type[] types = asm.GetTypes(); IDictionary<int, Type> typeMap = new Dictionary<int, Type>(); int counter = 1; Console.WriteLine("Select example to run: "); List<Type> typeList = new List<Type>(); //循環遍歷當前運行程序集的全部類 foreach (Type t in types) { //將實現了IExample接口的類加入到typeList集合中 if (new List<Type>(t.GetInterfaces()).Contains(typeof(IExample))) { typeList.Add(t); } } typeList.Sort(new TypeNameComparer()); //循環將序號 類名 加入到typeMap字典中 foreach (Type t in typeList) { string counterString = string.Format("[{0}]", counter).PadRight(4); Console.WriteLine("{0} {1} {2}", counterString, t.Namespace.Substring(t.Namespace.LastIndexOf(".") + 1), t.Name); typeMap.Add(counter++, t); } Console.WriteLine(); Console.Write("> "); //選擇要運行的類的序號 int num = Convert.ToInt32(Console.ReadLine()); //獲取該類的Type Type eType = typeMap[num]; //獲得該類的實例 IExample example = ObjectUtils.InstantiateType<IExample>(eType); //運行Run() example.Run(); Console.WriteLine("Example run successfully."); } catch (Exception ex) { Console.WriteLine("Error running example: " + ex.Message); Console.WriteLine(ex.ToString()); } Console.Read(); } /// <summary> /// 用於排序的比較器 /// </summary> public class TypeNameComparer : IComparer<Type> { public int Compare(Type t1, Type t2) { if (t1.Namespace.Length > t2.Namespace.Length) { return 1; } if (t1.Namespace.Length < t2.Namespace.Length) { return -1; } return t1.Namespace.CompareTo(t2.Namespace); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Quartz.Examples { /// <summary> /// Interface for examples. /// </summary> /// <author>Marko Lahma (.NET)</author> public interface IExample { string Name { get; } void Run(); } }
運行結果以下:
2016-04-23 00:37:43,679 [1] INFO Quartz.Impl.StdSchedulerFactory.Instantiate(D:
\Quartz.NET-2.3.2\src\Quartz\Impl\StdSchedulerFactory.cs:1021) - Quartz scheduler'DefaultQuartzScheduler' initialized
2016-04-23 00:37:43,681 [1] INFO Quartz.Impl.StdSchedulerFactory.Instantiate(D:
\Quartz.NET-2.3.2\src\Quartz\Impl\StdSchedulerFactory.cs:1023) - Quartz scheduler version: 2.3.2.0
2016-04-23 00:37:43,683 [1] INFO Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:29) - ------- 初始化完成 -----------
2016-04-23 00:37:43,684 [1] INFO Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:35) - ------- 調度做業 -------------------
2016-04-23 00:37:43,697 [1] INFO Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:50) - group1.job1 will run at: Fri, 22 Apr 2016 16:38:00 GMT
2016-04-23 00:37:43,697 [1] INFO Quartz.Core.QuartzScheduler.Start(D:\Quartz.NET-2.3.2\src\Quartz\Core\QuartzScheduler.cs:441) - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
2016-04-23 00:37:43,697 [1] INFO Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:54) - ------- 開始調度 -----------------
2016-04-23 00:37:43,697 [1] INFO Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:57) - ------- 等待2分鐘.... -------------
2016-04-23 00:38:00,044 [DefaultQuartzScheduler_Worker-1] INFO Quartz.Examples.SayHelloJob.Execute(C:\Users\Administrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloJob.cs:25)
- Hello, everyone, I'm YZR. - Sat, 23 Apr 2016 00:38:00 GMT
2016-04-23 00:38:20,000 [DefaultQuartzScheduler_Worker-2] INFO Quartz.Examples.SayHelloJob.Execute(C:\Users\Administrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloJob.cs:25)
- Hello, everyone, I'm YZR. - Sat, 23 Apr 2016 00:38:20 GMT
效果一樣也是每20秒運行一次做業,但這只是Quartz.Net框架一個簡單的任務調度演示,它擁有着更多複雜有用的功能以及特色,咱們在下篇會正式進入Quartz.Net的使用話題。