Quartz.net使用總結


進來項目中用到了   任務調度  來實現短信發送網關,所以這里分享下 Quartz.net 的使用經驗。 任務調度選用了 Quartz.net 來實現,之前用的是C#中自帶的window服務安裝,這次也打算用Topshel來做window服務,其實感覺差不多。ok,接下來說下  Quartz.net  在開發中的使用:

Quartz.NET簡介

作業調度的目標在於按照預先確定的時間和指定的順序來確保高效的數據處理流程,從而最大限度的使用系統資源。批處理流程是一種在無需最終用戶干預的方式下在后台通過順序方式運行的操作。

     Quartz.NET是一個開源的作業調度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#寫成,可用於winform和asp.net應用中。它提供了巨大的靈活性而不犧牲簡單性。你能夠用它來為執行一個作業而創建簡單的或復雜的調度。它有很多特征,如:數據庫支持,集群,插件,支持cron-like表達式等等。

Quartz.NET 是一個開源的作業調度框架,它可以被在小型應用程序甚至是企業級的應用程序。它有如下幾個特點:

  • API 操作簡單,只要幾行簡單的代碼你就可以在應用程序里面實現自己的作業調度,並實時監視作業執行情況
  • 觸發器功能強大,比 Windows 的任務計划提供更細的觸發粒度,你可以使用“Cron表達式(后文將介紹)”來實現如:每周星期一到星期五 8:00am,5:00pm(工作時間) 執行某一件任務
  • 良好的可擴展性,它基於接口編程,你可以實現自己的 Schedule 調度器,Job 作業,以及 Trigger 觸發器等
  • 作業可以保存在 RAM 中,也可以持久化到數據庫,支持多種數據庫類型:SqlServer、Oracle、MySql等
  • 集群,這是一個高級應用,可以在多台計算機之間創建負載平衡、容錯處理

Quartz.NET使用

首先引用下面的dll

 

前4個是Quartz.NET使用所必須的,Toshelf是用來做window服務所用的

添加QuartzHelp類庫

      添加JobDemo.cs,實現IJob接口。

 1 namespace QuartzHelp
 2 {
 3     public class JobDemo : IJob
 4     {
 5         //日志對象
 6         private static readonly ILog logger = LogManager.GetLogger(typeof(JobDemo));
 7 
 8         public void Execute(IJobExecutionContext context)
 9         {
10             logger.Info("JobDemo開始運作,模擬處理200ms的程序");
11             Thread.Sleep(200);
12             logger.Info("JobDemo處理完");
13         }
14     }
15 }
View Code

添加 WindowControl 控制台

     添加Service.cs文件,作為任務調度的入口

 1 namespace WindowControl
 2 {
 3     public class Service
 4     {
 5         private readonly ILog logger;
 6         private IScheduler scheduler;
 7         public Service()
 8         {
 9             logger = LogManager.GetLogger(typeof(Service));
10             ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
11             scheduler = schedulerFactory.GetScheduler();
12         }
13 
14         public void Start()
15         {
16             scheduler.Start();
17             logger.Info("Quartz服務成功啟動");
18         }
19 
20         public void Stop()
21         {
22             scheduler.Shutdown(true);
23             logger.Info("Quartz服務成功終止");
24         }
25 
26     }
27 }
View Code

     在Program.cs文件中,啟動任務調度

 1 namespace WindowControl
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             HostFactory.Run(x =>
 8             {
 9                 x.Service<Service>((s) =>
10                 {
11                     s.SetServiceName("ser");
12                     s.ConstructUsing(name => new Service());
13                     s.WhenStarted((t) => t.Start());
14                     s.WhenStopped((t) => t.Stop());
15                 });
16 
17                 x.RunAsLocalSystem();
18 
19                 //服務的描述
20                 x.SetDescription("任務服務安裝測試");
21                 //服務的顯示名稱
22                 x.SetDisplayName("MyDisplayName");
23                 //服務名稱
24                 x.SetServiceName("MyServiceName");
25 
26             });
27         }
28     }
29 }
View Code

 添加配置文件  

   新建一個Configs的文件夾,首先添加quartz_jobs.xml(作為 調度任務 的配置文件)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <!-- This file contains job definitions in schema version 2.0 format -->
 4 
 5 <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
 6 
 7   <processing-directives>
 8     <!-- 在計划作業和觸發器是應遵循的命令和原則 -->
 9     <overwrite-existing-data>true</overwrite-existing-data>
10   </processing-directives>
11 
12   <schedule>
13     <job>
14       <name>myJob</name>
15       <group>myJobGroup</group>
16       <description>第一個工作任務</description>
17       <job-type>QuartzHelp.JobDemo, QuartzHelp</job-type>
18       <durable>true</durable>
19       <recover>false</recover>
20     </job>
21     <trigger>
22       <cron>
23         <name>Trigger</name>
24         <group>TriggerGroup</group>
25         <description>Simple trigger to simply fire sample job</description>
26         <job-name>myJob</job-name>
27         <job-group>myJobGroup</job-group>
28         <!--每10秒中執行一次-->
29         <cron-expression>0/01 * * * * ?</cron-expression>
30       </cron>
31     </trigger>
32   </schedule>
33 </job-scheduling-data>
View Code

quartz_jobs.xml配置項說明:

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <!-- This file contains job definitions in schema version 2.0 format -->
 3 
 4 <!--在2.0版本中根結點由<quartz> 變為了<job-scheduling-data>-->
 5  <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
 6 
 7    <!--保持默認配置即可,具體作用有待研究-->
 8    <processing-directives>
 9     <overwrite-existing-data>true</overwrite-existing-data>
10   </processing-directives>
11 
12    <!--任務調度集合-->
13    <schedule>
14      <!--2.0版本中的job相當於1.x版本中的<job-detail>,這個節點是用來定義每個具體的任務的,多個任務請創建多個job節點即可-->
15      <job>
16        <!--任務名稱,同一個group中多個job的name不能相同,若未設置group則所有未設置group的job為同一個分組(必須設置)-->
17        <name>sampleJob</name>
18        <!--任務所屬分組,用於標識任務所屬分組-->
19        <group>sampleGroup</group>
20        <!--工作任務的描述,用於描述任務具體內容-->
21       <description>Sample job for Quartz Server</description>
22        <!--任務類型,任務的具體類型及所屬程序集,格式:實現了IJob接口的包含完整命名空間的類名,程序集名稱-->
23        <job-type>Quartz.Server.SampleJob, Quartz.Server</job-type>
24        <!--<durable>(持久性)-如果一個Job是不持久的, 一旦沒有觸發器與之關聯,它就會被從scheduler 中自動刪除-->
25       <durable>true</durable>
26       <recover>false</recover>
27      
28     </job>
29      <!--trigger 任務觸發器,用於定義使用何種方式觸發任務(job),同一個job可以定義多個trigger ,多個trigger 各自獨立的執行調度,每個trigger 中必須且只能定義一種觸發器類型(calendar-interval、simple、cron)
30      calendar-interval 一種觸發器類型,使用較少,此處略過-->
31      <trigger>
32        <!--簡單任務的觸發器,可以調度用於重復執行的任務-->
33        <simple>
34          <!--觸發器名稱,同一個分組中的名稱必須不同-->
35          <name>sampleSimpleTrigger</name>
36          <!--觸發器組-->
37          <group>sampleSimpleGroup</group>
38          <!--觸發器描述-->
39          <description>Simple trigger to simply fire sample job</description>
40          <!--要調度的任務名稱,該job-name必須和對應job節點中的name完全相同-->
41          <job-name>sampleJob</job-name>
42          <!--調度任務(job)所屬分組,該值必須和job中的group完全相同-->
43          <job-group>sampleGroup</job-group>
44          <!--start-time(選填) 任務開始執行時間utc時間,北京時間需要+08:00,如:<start-time>2012-04-01T08:00:00+08:00</start-time>表示北京時間2012年4月1日上午8:00開始執行,注意服務啟動或重啟時都會檢測此屬性,若沒有設置此屬性或者start-time設置的時間比當前時間較早,則服務啟動后會立即執行一次調度,若設置的時間比當前時間晚,服務會等到設置時間相同后才會第一次執行任務,一般若無特殊需要請不要設置此屬性-->
45          <misfire-instruction>SmartPolicy</misfire-instruction>
46          <!--任務執行次數,如:<repeat-count>-1</repeat-count>表示無限次執行-->
47          <repeat-count>-1</repeat-count>
48          <!--任務觸發間隔(毫秒)-->
49          <repeat-interval>10000</repeat-interval>
50         </simple>    
51     </trigger>
52     <job>
53         <name>CommissionJob</name>
54         <group>CommissionJob</group>
55         <description>Sample job for Quartz Server</description>
56         <job-type>Settlement.Jobs.CommissionJob, Settlement.Jobs</job-type>
57         <durable>true</durable>
58         <recover>false</recover>
59      
60     </job>
61      <trigger>
62        <!--cron復雜任務觸發器使用cron表達式定制任務調度-->
63        <cron>
64           <name>sampleSimpleTrigger2</name>
65           <group>sampleSimpleTrigger2</group>
66           <job-name>sampleJob2</job-name>
67           <job-group>sampleGroup2</job-group>
68          <!--start-time(選填) 任務開始執行時間utc時間,北京時間需要+08:00,如:<start-time>2012-04-01T08:00:00+08:00</start-time>表示北京時間2012年4月1日上午8:00開始執行,注意服務啟動或重啟時都會檢測此屬性,若沒有設置此屬性,服務會根據cron-expression的設置執行任務調度;若start-time設置的時間比當前時間較早,則服務啟動后會忽略掉cron-expression設置,立即執行一次調度,之后再根據cron-expression執行任務調度;若設置的時間比當前時間晚,則服務會在到達設置時間相同后才會應用cron-expression,根據規則執行任務調度,一般若無特殊需要請不要設置此屬性-->
69          <!--cron表達式-->
70          <cron-expression>0/10 * * * * ?</cron-expression>
71         </cron>  
72     </trigger> 
73   </schedule>  
74 </job-scheduling-data>
View Code

具體可以參考:http://www.cnblogs.com/h20064528/archive/2012/07/17/2595636.html

Quartz的cron表達式

一個cron表達式有至少6個(也可能7個)有空格分隔的時間元素。按順序依次為1.秒(0~592.分鍾(0~593.小時(0~234.天(月)(0~31,但是你需要考慮你月的天數)5.月(0~116.天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)7.年份(19702099)

其中每個元素可以是一個值(如6),一個連續區間(9-12),一個間隔時間(8-18/4)(/表示每隔4小時),一個列表(1,3,5),通配符。由於"月份中的日期""星期中的日期"這兩個元素互斥的,必須要對其中一個設置?.

0 0 10,14,16 * * ? 每天上午10點,下午2點,4點0 0/30 9-17 * * ??? 朝九晚五工作時間內每半小時0 0 12 ? * WED 表示每個星期三中午12點

有些子表達式能包含一些范圍或列表例如:子表達式(天(星期))可以為 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT”

“*”字符代表所有可能的值因此,“*”在子表達式(月)里表示每個月的含義,“*”在子表達式(天(星期))表示星期的每一天

“/”字符用來指定數值的增量例如:在子表達式(分鍾)里的“0/15”表示從第0分鍾開始,每15分鍾 ;在子表達式(分鍾)里的“3/20”表示從第3分鍾開始,每20分鍾(它和“32343”)的含義一樣“?”字符僅被用於天(月)和天(星期)兩個子表達式,表示不指定值當2個子表達式其中之一被指定了值以后,為了避免沖突,需要將另一個子表達式的值設為“?”

“L” 字符僅被用於天(月)和天(星期)兩個子表達式,它是單詞“last”的縮寫

但是它在兩個子表達式里的含義是不同的。

在天(月)子表達式中,“L”表示一個月的最后一天 ,在天(星期)自表達式中,“L”表示一個星期的最后一天,也就是SAT

如果在“L”前有具體的內容,它就具有其他的含義了

例如:“6L”表示這個月的倒數第6天,“FRIL”表示這個月的最后一個星期五

注意:在使用“L”參數時,不要指定列表或范圍,因為這會導致問題

============================================

CronTrigger配置完整格式為: [秒] [分] [小時] [日] [月] [周] [年]

 

 序號    說明     是否必填     允許填寫的值    允許的通配符    

 1     秒     是     0-59       , - * /    

 2     分     是     0-59       , - * /    

 3    小時     是     0-23      , - * /    

 4     日     是     1-31      , - * ? / L W    

 5     月     是     1-12 or JAN-DEC      , - * /    

 6     周     是     1-7 or SUN-SAT      , - * ? / L #    

 7     年     否     empty 或 1970-2099      , - * /    

通配符說明:*表示所有值. 例如:在分的字段上設置 "*",表示每一分鍾都會觸發。? 表示不指定值。使用的場景為不需要關心當前設置這個字段的值。例如:要在每月的10號觸發一個操作,但不關心是周幾,所以需要周位置的那個字段設置為"?" 具體設置為 0 0 0 10 * ?- 表示區間。例如 在小時上設置 "10-12",表示 10,11,12點都會觸發。, 表示指定多個值,例如在周字段上設置 "MON,WED,FRI" 表示周一,周三和周五觸發/用於遞增觸發。如在秒上面設置"5/15" 表示從5秒開始,每增15秒觸發(5,20,35,50)。 在月字段上設置'1/3'所示每月1號開始,每隔三天觸發一次。L 表示最后的意思。在日字段設置上,表示當月的最后一天(依據當前月份,如果是二月還會依據是否是潤年[leap]), 在周字段上表示星期六,相當於"7""SAT"。如果在"L"前加上數字,則表示該數據的最后一個。例如在周字段上設置"6L"這樣的格式,則表示“本月最后一個星期五" W 表示離指定日期的最近那個工作日(周一至周五). 例如在日字段上設置"15W",表示離每月15號最近的那個工作日觸發。如果15號正好是周六,則找最近的周五(14號)觸發, 如果15號是周未,則找最近的下周一(16號)觸發.如果15號正好在工作日(周一至周五),則就在該天觸發。如果指定格式為 "1W",它則表示每月1號往后最近的工作日觸發。如果1號正是周六,則將在3號下周一觸發。(注,"W"前只能設置具體的數字,不允許區間"-").# 序號(表示每月的第幾個周幾),例如在周字段上設置"6#3"表示在每月的第三個周六.注意如果指定"#5",正好第五周沒有周六,則不會觸發該配置(用在母親節和父親節再合適不過了) ;小提示:'L'和 'W'可以一組合使用。如果在日字段上設置"LW",則表示在本月的最后一個工作日觸發;周字段的設置,若使用英文字母是不區分大小寫的,即MON與mon相同;常用示例:

 

0 0 12 * * ?    每天12點觸發    

0 15 10 ? * *    每天10點15分觸發    

0 15 10 * * ?    每天10點15分觸發    

0 15 10 * * ? *    每天10點15分觸發    

0 15 10 * * ? 2005    2005年每天10點15分觸發    

0 * 14 * * ?    每天下午的 2點到2點59分每分觸發    

0 0/5 14 * * ?    每天下午的 2點到2點59分(整點開始,每隔5分觸發)    

0 0/5 14,18 * * ?    每天下午的 2點到2點59分、18點到18點59分(整點開始,每隔5分觸發)    

0 0-5 14 * * ?    每天下午的 2點到2點05分每分觸發    

0 10,44 14 ? 3 WED    3月分每周三下午的 2點10分和2點44分觸發    

0 15 10 ? * MON-FRI    從周一到周五每天上午的10點15分觸發    

0 15 10 15 * ?    每月15號上午10點15分觸發    

0 15 10 L * ?    每月最后一天的10點15分觸發    

0 15 10 ? * 6L    每月最后一周的星期五的10點15分觸發    

0 15 10 ? * 6L 2002-2005    從2002年到2005年每月最后一周的星期五的10點15分觸發    

0 15 10 ? * 6#3    每月的第三周的星期五開始觸發    

0 0 12 1/5 * ?    每月的第一個中午開始每隔5天觸發一次    

0 11 11 11 11 ?    每年的11月11號 11點11分觸發(光棍節)   
View Code

具體可以參考:http://www.cnblogs.com/yaowen/p/3779284.html

   然后配置app.config文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <configuration>
 3   <configSections>
 4     <section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
 5     <sectionGroup name="common">
 6       <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging"/>
 7     </sectionGroup>
 8   </configSections>
 9   <common>
10     <logging>
11       <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net">
12         <!-- inline :log4net 節點在App.Config/Web.Config 文件中配置        file:使用外置配置文件 (需要configFile參數配合使用,<arg key="configFile" value="外部配置文件")         file-watch: 與"file"一樣,只是多了一個監視外部配置文件的變動功能,如果有變動則重新加載配置。        external:IBatis將不會嘗試配置Log4Net。        -->
13         <arg key="configType" value="file-watch"/>
14         <!-- 這里必須要保證在生成的目錄下面有Configs這個文件夾-->
15         <arg key="configFile" value="~/Configs/quartz_log4net.config"/>
16       </factoryAdapter>
17     </logging>
18   </common>
19   <quartz>
20     <add key="quartz.scheduler.instanceName" value="TaskScheduler"/>
21     <add key="quartz.scheduler.instanceId" value="AUTO"/>
22     <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
23     <add key="quartz.threadPool.threadCount" value="5"/>
24     <add key="quartz.threadPool.threadPriority" value="Normal"/>
25     <add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz"/>
26     <!-- 這里必須要保證在生成的目錄下面有Configs這個文件夾-->
27     <add key="quartz.plugin.xml.fileNames" value="~/Configs/quartz_jobs.config"/>
28     <add key="quartz.plugin.xml.scanInterval" value="600"/>
29   </quartz>
30   <startup>
31     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
32   </startup>
33 </configuration>
View Code

  最后,為日記記錄配置quartz_log4net.config文件,當然,你也可以不用獨立出來,直接配置在app.config文件中也是可以的

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <log4net>
 3   <appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
 4     <param name="File" value="Log\\" />
 5     <param name="AppendToFile" value="true" />
 6     <param name="MaxFileSize" value="10240" />
 7     <param name="MaxSizeRollBackups" value="100" />
 8     <param name="StaticLogFileName" value="false" />
 9     <param name="DatePattern" value="yyyyMMdd'.log'" />
10     <param name="RollingStyle" value="Date" />
11     <layout type="log4net.Layout.PatternLayout">
12       <param name="ConversionPattern" value="%n日志時間:%d [%t] %n日志級別:%-5p %n日 志 類:%c [%L] %n%m %n" />
13     </layout>
14   </appender>
15   <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
16     <layout type="log4net.Layout.PatternLayout">
17       <conversionPattern value="%5level [%thread] - %message%newline" />
18     </layout>
19   </appender>
20   <root>
21     <level value="INFO" />
22     <appender-ref ref="ConsoleAppender" />
23     <appender-ref ref="FileAppender" />
24   </root>
25 </log4net>
View Code

 好了,接下來運行程序,就可以看見任務已經啟動了:

 

安裝window服務

用了Toshelf后,不需要用InstallUtil.exe來安裝服務了,很簡單的一句,直接控制台下執行:WindowControl.exe install 就好了。

 

每一次開發都是一次進步和積累,每一次分享都是一次學習和復習的機會,希望大家有更好的東西也能分享出來,一起學習。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM