C# Quartz.NET 配置問題詳解

最新項目中的windowService所有換成Quartz.NET和TopShelf,總結了一下配置的過程,寫個比較詳細的教程html

1.下載和安裝Quartz.NET和TopShelf

直接在NuGet裏面敲Quartz.netTopShelf 安裝到本身項目就能夠了 ,建議直接用NuGet,畢竟版本和插件管理是比較麻煩的事,Ps:TopShelf是將任何一個函數變成一個window 服務的工具,啥均可以變成服務express

安裝Quartz.NETapache

image

安裝 TopShelfapp

image

首先是另外一位大神的微博:http://www.cnblogs.com/jys509/p/4628926.html (微博很清新,內容很詳細,當初我是看這裏裝的)less

源碼下載:Quartz 2.3 示例源碼下載 tcp

Quartz.NET 官網地址:http://www.quartz-scheduler.net/ ide

Quartz.NET 官方使用教程地址:http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/using-quartz.html (看翻譯好的不如本身邊機翻邊本身看,也比看翻譯好的舒服,別人都嚼過了怎麼會香)函數

Quartz.NET 官網安裝教程地址:http://www.quartz-scheduler.net/documentation/quartz-2.x/quick-start.html工具

 2.配置QuartZ

初始配置

對於QuartZ初始配置的方式有三種:學習

1.app.config裏面直接進行配置(推薦)

先在  <configSections>目錄下加配置,以下內容,log4net和entityFramework 是咱們項目本身用的,能夠無視

1   <configSections>
2     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a" />
3     <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
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>

而後在<configuration>根目錄下加入<quartz>目錄就能夠了,這種方式比較方便,也統一了config

1   <quartz>
2     <add key="quartz.plugin.xml.fileNames" value="~/quartz_jobs.xml"/>
3     <add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz"/>
4     <add key="quartz.scheduler.instanceName" value=" EDMServiceQuartzTest"/>
5     <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
6     <add key="quartz.threadPool.threadCount" value="10"/>
7     <add key="quartz.threadPool.threadPriority" value="Normal"/>
8   </quartz>

 2.添加quartz.config文件或者在代碼中配置文件

quartz.config:文件大概長這樣,直接放到根目錄就能夠了,官網demo裏面是沒有的,因此不太建議用這種方法

# You can configure your scheduler in either <quartz> configuration section  
# or in quartz properties file  
# Configuration section has precedence  
  
quartz.scheduler.instanceName = ServerScheduler  
  
# configure thread pool info  
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz  
quartz.threadPool.threadCount = 10  
quartz.threadPool.threadPriority = Normal  
  
# job initialization plugin handles our xml reading, without it defaults are used  
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz  
quartz.plugin.xml.fileNames = ~/quartz_jobs.xml 
  
# export this server to remoting context  
quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz  
quartz.scheduler.exporter.port = 555  
quartz.scheduler.exporter.bindName = QuartzScheduler  
quartz.scheduler.exporter.channelType = tcp  
quartz.scheduler.exporter.channelName = httpQuartz  

記得要在屬性-複製到輸出目錄,改爲始終複製

image

代碼中配置文件:這種是最不推薦的了,可是官網裏面有demo,Example15,因此就放出來看看,須要動態配置的能夠看下,代碼以下(Example15)

  1 using System.Collections.Specialized;
  2 using System.Threading;
  3 
  4 using Common.Logging;
  5 
  6 using Quartz.Impl;
  7 using Quartz.Impl.Calendar;
  8 
  9 #region License
 10 /* 
 11  * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. 
 12  * 
 13  * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 14  * use this file except in compliance with the License. You may obtain a copy 
 15  * of the License at 
 16  * 
 17  *   http://www.apache.org/licenses/LICENSE-2.0 
 18  *   
 19  * Unless required by applicable law or agreed to in writing, software 
 20  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
 21  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
 22  * License for the specific language governing permissions and limitations 
 23  * under the License.
 24  * 
 25  */
 26 #endregion
 27 
 28 using System.Collections.Specialized;
 29 using System.Threading;
 30 
 31 using Common.Logging;
 32 
 33 using Quartz.Impl;
 34 using Quartz.Impl.Calendar;
 35 
 36 namespace Quartz.Examples.Example15
 37 {
 38     /// <summary>
 39     /// This example will demonstrate how configuration can be
 40     /// done using an XML file.
 41     /// </summary>
 42     /// <author>Marko Lahma (.NET)</author>
 43     public class XmlConfigurationExample : IExample
 44     {
 45         public string Name
 46         {
 47             get { return GetType().Name; }
 48         }
 49 
 50         public void Run()
 51         {
 52             ILog log = LogManager.GetLogger(typeof(XmlConfigurationExample));
 53 
 54             log.Info("------- Initializing ----------------------");
 55 
 56             // First we must get a reference to a scheduler
 57             NameValueCollection properties = new NameValueCollection();
 58             properties["quartz.scheduler.instanceName"] = "XmlConfiguredInstance";
 59             
 60             // set thread pool info
 61             properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
 62             properties["quartz.threadPool.threadCount"] = "5";
 63             properties["quartz.threadPool.threadPriority"] = "Normal";
 64 
 65             // job initialization plugin handles our xml reading, without it defaults are used
 66             properties["quartz.plugin.xml.type"] = "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz";
 67             properties["quartz.plugin.xml.fileNames"] = "~/quartz_jobs.xml";
 68 
 69 
 70             ISchedulerFactory sf = new StdSchedulerFactory(properties);
 71             IScheduler sched = sf.GetScheduler();
 72             
 73             // we need to add calendars manually, lets create a silly sample calendar
 74             var dailyCalendar = new DailyCalendar("00:01", "23:59");
 75             dailyCalendar.InvertTimeRange = true;
 76             sched.AddCalendar("cal1", dailyCalendar, false, false);
 77 
 78             log.Info("------- Initialization Complete -----------");
 79 
 80             // all jobs and triggers are now in scheduler
 81 
 82 
 83             // Start up the scheduler (nothing can actually run until the 
 84             // scheduler has been started)
 85             sched.Start();
 86             log.Info("------- Started Scheduler -----------------");
 87 
 88             // wait long enough so that the scheduler as an opportunity to 
 89             // fire the triggers
 90             log.Info("------- Waiting 30 seconds... -------------");
 91 
 92             try
 93             {
 94                 Thread.Sleep(30*1000);
 95             }
 96             catch (ThreadInterruptedException)
 97             {
 98             }
 99 
100             // shut down the scheduler
101             log.Info("------- Shutting Down ---------------------");
102             sched.Shutdown(true);
103             log.Info("------- Shutdown Complete -----------------");
104         }
105     }
106 }
Example15

2.配置Trigger和Job

1.經過quartz_jobs.xml配置(推薦)

剛剛下載好的項目裏面是沒有這個文件的,能夠直接新建一個或者直接把官方Demo裏面的文件複製過來,大概長這樣

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData"
 4         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5                  version="2.0">
 6 
 7   <processing-directives>
 8     <overwrite-existing-data>true</overwrite-existing-data>
 9   </processing-directives>
10 
11   <schedule>
12     
13     <job>
14       <name>jobName1</name>
15       <group>jobGroup1</group>
16       <description>jobDesciption1</description>
17       <job-type>Quartz.Examples.Example15.SimpleJob, Quartz.Examples</job-type>
18       <durable>true</durable>
19       <recover>false</recover>
20       <job-data-map>
21         <entry>
22           <key>key0</key>
23           <value>value0</value>
24         </entry>
25         <entry>
26           <key>key1</key>
27           <value>value1</value>
28         </entry>
29         <entry>
30           <key>key2</key>
31           <value>value2</value>
32         </entry>
33       </job-data-map>
34     </job>
35     
36     <trigger>
37       <simple>
38         <name>simpleName</name>
39         <group>simpleGroup</group>
40         <description>SimpleTriggerDescription</description>
41         <job-name>jobName1</job-name>
42         <job-group>jobGroup1</job-group>
43         <start-time>1982-06-28T18:15:00.0Z</start-time>
44         <end-time>2020-05-04T18:13:51.0Z</end-time>
45         <misfire-instruction>SmartPolicy</misfire-instruction>
46         <repeat-count>100</repeat-count>
47         <repeat-interval>3000</repeat-interval>
48       </simple>
49     </trigger>
50 
51   </schedule>
52   
53 </job-scheduling-data>
quartz_jobs.xml

首先要在1裏面添加一個節點 quartz.plugin.xml.fileNames=~/quartz_jobs.xml,而後放入xml就能夠了

節點的具體用途能夠看看最上面另外一個文章的連接<trigger>節點的配置推薦<cron>

要注意的是配置<trigger><job> 的時候和每一個節點要按照必定的順序,

好比<name></name>必須在<job-name></job-name>前面 不然就會出錯,具體的看官方demo裏面的quartz_jobs.xml,試一試就知道了是否能夠添加了(本身項目爲啥出不來?筆者也在研究)

2.直接在代碼裏面配置

官網Demo裏面不少都是在代碼裏面編寫的,不太推薦,可是這種初始化的風格的確能夠拿來學習一下。拿幾個例子看下:

官網的HelloJob(Example1)
 1 #region License
 2 
 3 /* 
 4  * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. 
 5  * 
 6  * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 7  * use this file except in compliance with the License. You may obtain a copy 
 8  * of the License at 
 9  * 
10  *   http://www.apache.org/licenses/LICENSE-2.0 
11  *   
12  * Unless required by applicable law or agreed to in writing, software 
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
15  * License for the specific language governing permissions and limitations 
16  * under the License.
17  * 
18  */
19 
20 #endregion
21 
22 using System;
23 using System.Threading;
24 
25 using Common.Logging;
26 #if !NET_20
27 #endif
28 using Quartz.Impl;
29 
30 namespace Quartz.Examples.Example1
31 {
32     /// <summary> 
33     /// This Example will demonstrate how to start and shutdown the Quartz 
34     /// scheduler and how to schedule a job to run in Quartz.
35     /// </summary>
36     /// <author>Bill Kratzer</author>
37     /// <author>Marko Lahma (.NET)</author>
38     public class SimpleExample : IExample
39     {
40         public string Name
41         {
42             get { throw new NotImplementedException(); }
43         }
44 
45         public virtual void Run()
46         {
47             ILog log = LogManager.GetLogger(typeof (SimpleExample));
48 
49             log.Info("------- Initializing ----------------------");
50 
51             // First we must get a reference to a scheduler
52             ISchedulerFactory sf = new StdSchedulerFactory();
53             IScheduler sched = sf.GetScheduler();
54 
55             log.Info("------- Initialization Complete -----------");
56 
57 
58             // computer a time that is on the next round minute
59             DateTimeOffset runTime = DateBuilder.EvenMinuteDate(DateTimeOffset.UtcNow);
60 
61             log.Info("------- Scheduling Job  -------------------");
62 
63             // define the job and tie it to our HelloJob class
64             IJobDetail job = JobBuilder.Create<HelloJob>()
65                 .WithIdentity("job1", "group1")
66                 .Build();
67 
68             // Trigger the job to run on the next round minute
69             ITrigger trigger = TriggerBuilder.Create()
70                 .WithIdentity("trigger1", "group1")
71                 .StartAt(runTime)
72                 .Build();
73 
74             // Tell quartz to schedule the job using our trigger
75             sched.ScheduleJob(job, trigger);
76             log.Info(string.Format("{0} will run at: {1}", job.Key, runTime.ToString("r")));
77 
78             // Start up the scheduler (nothing can actually run until the 
79             // scheduler has been started)
80             sched.Start();
81             log.Info("------- Started Scheduler -----------------");
82 
83             // wait long enough so that the scheduler as an opportunity to 
84             // run the job!
85             log.Info("------- Waiting 65 seconds... -------------");
86 
87             // wait 65 seconds to show jobs
88             Thread.Sleep(TimeSpan.FromSeconds(65));
89 
90             // shut down the scheduler
91             log.Info("------- Shutting Down ---------------------");
92             sched.Shutdown(true);
93             log.Info("------- Shutdown Complete -----------------");
94         }
95     }
96 }
Example1
Example5:一個job怎麼關聯兩個trigger
  1 #region License
  2 
  3 /* 
  4  * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. 
  5  * 
  6  * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  7  * use this file except in compliance with the License. You may obtain a copy 
  8  * of the License at 
  9  * 
 10  *   http://www.apache.org/licenses/LICENSE-2.0 
 11  *   
 12  * Unless required by applicable law or agreed to in writing, software 
 13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
 14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
 15  * License for the specific language governing permissions and limitations 
 16  * under the License.
 17  * 
 18  */
 19 
 20 #endregion
 21 
 22 using System;
 23 using System.Threading;
 24 
 25 using Common.Logging;
 26 
 27 using Quartz.Impl;
 28 
 29 namespace Quartz.Examples.Example5
 30 {
 31     /// <summary> 
 32     /// Demonstrates the behavior of <see cref="PersistJobDataAfterExecutionAttribute" />, 
 33     /// as well as how misfire instructions affect the firings of triggers of
 34     /// that have <see cref="DisallowConcurrentExecutionAttribute" /> present - 
 35     /// when the jobs take longer to execute that the frequency of the trigger's
 36     /// repetition.
 37     /// </summary>
 38     /// <remarks>
 39     /// <para>
 40     /// While the example is running, you should note that there are two triggers
 41     /// with identical schedules, firing identical jobs. The triggers "want" to fire
 42     /// every 3 seconds, but the jobs take 10 seconds to execute. Therefore, by the
 43     /// time the jobs complete their execution, the triggers have already "misfired"
 44     /// (unless the scheduler's "misfire threshold" has been set to more than 7
 45     /// seconds). You should see that one of the jobs has its misfire instruction
 46     /// set to <see cref="MisfireInstruction.SimpleTrigger.RescheduleNowWithExistingRepeatCount" />,
 47     /// which causes it to fire immediately, when the misfire is detected. The other
 48     /// trigger uses the default "smart policy" misfire instruction, which causes
 49     /// the trigger to advance to its next fire time (skipping those that it has
 50     /// missed) - so that it does not refire immediately, but rather at the next
 51     /// scheduled time.
 52     /// </para>
 53     /// </remarks>
 54     /// <author><a href="mailto:bonhamcm@thirdeyeconsulting.com">Chris Bonham</a></author>
 55     /// <author>Marko Lahma (.NET)</author>
 56     public class MisfireExample : IExample
 57     {
 58         public string Name
 59         {
 60             get { throw new NotImplementedException(); }
 61         }
 62 
 63         public virtual void Run()
 64         {
 65             ILog log = LogManager.GetLogger(typeof (MisfireExample));
 66 
 67             log.Info("------- Initializing -------------------");
 68 
 69             // First we must get a reference to a scheduler
 70             ISchedulerFactory sf = new StdSchedulerFactory();
 71             IScheduler sched = sf.GetScheduler();
 72 
 73             log.Info("------- Initialization Complete -----------");
 74 
 75             log.Info("------- Scheduling Jobs -----------");
 76 
 77             // jobs can be scheduled before start() has been called
 78 
 79             // get a "nice round" time a few seconds in the future...
 80 
 81             DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(null, 15);
 82 
 83             // statefulJob1 will run every three seconds
 84             // (but it will delay for ten seconds)
 85             IJobDetail job = JobBuilder.Create<StatefulDumbJob>()
 86                 .WithIdentity("statefulJob1", "group1")
 87                 .UsingJobData(StatefulDumbJob.ExecutionDelay, 10000L)
 88                 .Build();
 89 
 90             ISimpleTrigger trigger = (ISimpleTrigger) TriggerBuilder.Create()
 91                                                           .WithIdentity("trigger1", "group1")
 92                                                           .StartAt(startTime)
 93                                                           .WithSimpleSchedule(x  => x.WithIntervalInSeconds(3).RepeatForever())
 94                                                           .Build();
 95 
 96             DateTimeOffset ft = sched.ScheduleJob(job, trigger);
 97             log.Info(string.Format("{0} will run at: {1} and repeat: {2} times, every {3} seconds", job.Key, ft.ToString("r"), trigger.RepeatCount, trigger.RepeatInterval.TotalSeconds));
 98 
 99             // statefulJob2 will run every three seconds
100             // (but it will delay for ten seconds - and therefore purposely misfire after a few iterations)
101             job = JobBuilder.Create<StatefulDumbJob>()
102                 .WithIdentity("statefulJob2", "group1")
103                 .UsingJobData(StatefulDumbJob.ExecutionDelay, 10000L)
104                 .Build();
105 
106             trigger = (ISimpleTrigger) TriggerBuilder.Create()
107                                            .WithIdentity("trigger2", "group1")
108                                            .StartAt(startTime)
109                                            .WithSimpleSchedule(x => x
110                                                                  .WithIntervalInSeconds(3)
111                                                                  .RepeatForever()
112                                                                  .WithMisfireHandlingInstructionNowWithExistingCount()) // set misfire instructions
113                                            .Build();
114             ft = sched.ScheduleJob(job, trigger);
115 
116             log.Info(string.Format("{0} will run at: {1} and repeat: {2} times, every {3} seconds", job.Key, ft.ToString("r"), trigger.RepeatCount, trigger.RepeatInterval.TotalSeconds));
117 
118             log.Info("------- Starting Scheduler ----------------");
119 
120             // jobs don't start firing until start() has been called...
121             sched.Start();
122 
123             log.Info("------- Started Scheduler -----------------");
124 
125             try
126             {
127                 // sleep for ten minutes for triggers to file....
128                 Thread.Sleep(TimeSpan.FromMinutes(10));
129             }
130             catch (ThreadInterruptedException)
131             {
132             }
133 
134             log.Info("------- Shutting Down ---------------------");
135 
136             sched.Shutdown(true);
137 
138             log.Info("------- Shutdown Complete -----------------");
139 
140             SchedulerMetaData metaData = sched.GetMetaData();
141             log.Info(string.Format("Executed {0} jobs.", metaData.NumberOfJobsExecuted));
142         }
143     }
144 }
Example15

最後,不管是哪一種配置Trigger和Job的方法(xml或者代碼)都要記住如下幾點:

1.每一個Job能對應多個Trigger,可是每一個Trigger只能對應一個Job,因此建議把觸發時間相同的做業放在一個Job裏面也許會比較好,

2.Job配置到多個Trigger時須要配置 <durable>true</durable> 代碼裏面的是對應的是 .StoreDurably(),不然會報錯

三.Job和Trigger入門

過幾天會補上

相關文章
相關標籤/搜索