Quartz:首先我貼出來了兩段代碼(下方),可以看出,首先根據配置文件(quartz.config),包裝出一個Quartz.Core.QuartzScheduler instance,這是一個調度器,調度各個任務項(Jobs)的執行。這個調度器可以被Start、被Shutdown、被PauseA ...
Quartz:首先我貼出來了兩段代碼(下方),可以看出,首先會根據配置文件(quartz.config),包裝出一個Quartz.Core.QuartzScheduler
instance,這是一個調度器,調度各個任務項(Jobs)的執行。這個調度器可以被Start、被Shutdown、被PauseAll、被ResumeAll,這對應
了windows服務的開啟、停止、暫停、恢復。當啟動服務,我就調用調度器的Start(),停止服務我就調用調度器的Shutdown()方法。
namespace QTDemo { public class ServiceRunner : ServiceControl, ServiceSuspend { private readonly IScheduler scheduler; public ServiceRunner() { scheduler = StdSchedulerFactory.GetDefaultScheduler(); } public bool Start(HostControl hostControl) { scheduler.Start(); return true; }
// 摘要: // An implementation of Quartz.ISchedulerFactory that does all of it's work // of creating a Quartz.Core.QuartzScheduler instance based on the contents // of a properties file. public class StdSchedulerFactory : ISchedulerFactory { public const string AutoGenerateInstanceId = "AUTO"; public const string ConfigurationSectionName = "quartz"; public const string DefaultInstanceId = "NON_CLUSTERED"; public const string PropertiesFile = "quartz.config";
那TopShelf又扮演了什麼樣的角色呢
這是一個宿主服務的框架。和ServiceBase、ServiceInstaller那一套的目的一樣,都是用來創建Windows服務的。
項目示例
1、新建項目控制台應用程式‘QTDemo’
2、從NuGet安裝‘Quartz’,‘Topshelf’,‘Topshelf.Log4Net’
1 <?xml version="1.0" encoding="utf-8"?> 2 <packages> 3 <package id="Common.Logging" version="3.3.1" targetFramework="net45" /> 4 <package id="Common.Logging.Core" version="3.3.1" targetFramework="net45" /> 5 <package id="log4net" version="2.0.5" targetFramework="net45" /> 6 <package id="Quartz" version="2.3.3" targetFramework="net45" /> 7 <package id="Topshelf" version="3.3.1" targetFramework="net45" /> 8 <package id="Topshelf.Log4Net" version="3.3.1" targetFramework="net45" /> 9 </packages>
3、定義一個Job(一個任務項),繼承Quartz.IJob
1 using Quartz; 2 namespace QTDemo.QuartzJobs 3 { 4 public sealed class TestJob : IJob 5 { 6 public void Execute(IJobExecutionContext context) 7 { 8 CommonHelper.AppLogger.InfoFormat("TestJob測試"); 9 10 } 11 } 12 } 13
4、配置(新建)quartz.config、quartz_jobs.xml
quartz.config可直接使用,不用修改
1 # You can configure your scheduler in either <quartz> configuration section 2 # or in quartz properties file 3 # Configuration section has precedence 4 5 quartz.scheduler.instanceName = QuartzTest 6 7 # configure thread pool info 8 quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz 9 quartz.threadPool.threadCount = 10 10 quartz.threadPool.threadPriority = Normal 11 12 # job initialization plugin handles our xml reading, without it defaults are used 13 quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz 14 quartz.plugin.xml.fileNames = ~/quartz_jobs.xml 15 16 # export this server to remoting context 17 #quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz 18 #quartz.scheduler.exporter.port = 555 19 #quartz.scheduler.exporter.bindName = QuartzScheduler 20 #quartz.scheduler.exporter.channelType = tcp 21 #quartz.scheduler.exporter.channelName = httpQuartzView Code
quartz_jobs.xml根據實際的Job項修改
1 <?xml version="1.0" encoding="utf-8" ?> 2 <!-- This file contains job definitions in schema version 2.0 format --> 3 4 <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"> 5 6 <processing-directives> 7 <overwrite-existing-data>true</overwrite-existing-data> 8 </processing-directives> 9 10 <schedule> 11 12 <!--TestJob測試 任務配置 --> 13 <job> 14 <name>TestJob</name> 15 <group>Test</group> 16 <description>TestJob測試</description> 17 <job-type>QTDemo.QuartzJobs.TestJob,QTDemo</job-type> 18 <durable>true</durable> 19 <recover>false</recover> 20 </job> 21 <trigger> 22 <cron> 23 <name>TestJobTrigger</name> 24 <group>Test</group> 25 <job-name>TestJob</job-name> 26 <job-group>Test</job-group> 27 <!-- 從start-time起,每5s執行一次IJob.Execute --> 28 <start-time>2012-01-22T00:00:00+08:00</start-time> 29 <cron-expression>0/5 * * * * ?</cron-expression> 30 </cron> 31 </trigger> 32 33 </schedule> 34 </job-scheduling-data>
5、創建服務
入口:
1 using System; 2 using System.IO; 3 using Topshelf; 4 5 namespace QTDemo 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config")); 12 16 HostFactory.Run(x => 17 { 18 x.UseLog4Net(); 19 20 x.Service<ServiceRunner>(); 21 22 x.RunAsLocalSystem(); 23 24 x.SetDescription("Quartz+TopShelf實現Windows服務作業調度的一個示例Demo"); 25 x.SetDisplayName("QuartzTopShelfDemo服務"); 26 x.SetServiceName("QuartzTopShelfDemoService"); 27 28 x.EnablePauseAndContinue(); 29 30 }); 31 } 32 } 33 }
ServiceRunner.cs
1 using Quartz; 2 using Quartz.Impl; 3 using Topshelf; 4 5 namespace QTDemo 6 { 7 public class ServiceRunner : ServiceControl, ServiceSuspend 8 { 9 private readonly IScheduler scheduler; 10 11 public ServiceRunner() 12 { 13 scheduler = StdSchedulerFactory.GetDefaultScheduler(); 14 } 15 16 public bool Start(HostControl hostControl) 17 { 18 scheduler.Start(); 19 return true; 20 } 21 22 public bool Stop(HostControl hostControl) 23 { 24 scheduler.Shutdown(false); 25 return true; 26 } 27 28 public bool Continue(HostControl hostControl) 29 { 30 scheduler.ResumeAll(); 31 return true; 32 } 33 34 public bool Pause(HostControl hostControl) 35 { 36 scheduler.PauseAll(); 37 return true; 38 } 39 40 } 41 }
log4net配置文件,可直接使用
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <configSections> 4 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> 5 </configSections> 6 7 <log4net> 8 <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"> 9 <!--日誌路徑--> 10 <param name= "File" value= "Log\"/> 11 <!--是否是向文件中追加日誌--> 12 <param name= "AppendToFile" value= "true"/> 13 <!--log保留天數--> 14 <param name= "MaxSizeRollBackups" value= "10"/> 15 <!--日誌文件名是否是固定不變的--> 16 <param name= "StaticLogFileName" value= "false"/> 17 <!--日誌文件名格式為:2008-08-31.log--> 18 <param name= "DatePattern" value= "yyyy-MM-dd".read.log""/> 19 <!--日誌根據日期滾動--> 20 <param name= "RollingStyle" value= "Date"/> 21 <layout type="log4net.Layout.PatternLayout"> 22 <param name="ConversionPattern" value="%date{HH:mm:ss,fff} %-5p-%m%n" /> 23 </layout> 24 </appender> 25 26 <!-- 控制台前臺顯示日誌 --> 27 <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> 28 <mapping> 29 <level value="ERROR" /> 30 <foreColor value="Red, HighIntensity" /> 31 </mapping> 32 <mapping> 33 <level value="Info" /> 34 <foreColor value="Green" /> 35 </mapping> 36 <layout type="log4net.Layout.PatternLayout"> 37 <conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" /> 38 </layout> 39 40 <filter type="log4net.Filter.LevelRangeFilter"> 41 <param name="LevelMin" value="Info" /> 42 <param name="LevelMax" value="Fatal" /> 43 </filter> 44 </appender> 45 46 <root> 47 <!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) --> 48 <level value="all" /> 49 <appender-ref ref="ColoredConsoleAppender"/> 50 <appender-ref ref="RollingLogFileAppender"/> 51 </root> 52 53 </log4net> 54 </configuration>View Code
6、quartz.config、quartz_jobs.xml、log4net.config都設置成‘始終複製’
7、直接F5,調試,發現TestJob每5s執行一次
8、安裝成Windows服務
用Release編一個版本
然後用命令行安裝服務
服務面板里可以找到此服務
啟動之,查看日誌文件,服務運行正常
23:23:52,171 INFO -Configuration Result: [Success] Name QuartzTopShelfDemoService [Success] DisplayName QuartzTopShelfDemo服務 [Success] Description Quartz+TopShelf實現Windows服務作業調度的一個示例Demo [Success] ServiceName QuartzTopShelfDemoService 23:23:52,185 INFO -Topshelf v3.3.154.0, .NET Framework v4.0.30319.34014 23:23:52,194 ERROR-The QuartzTopShelfDemoService service can only be installed as an administrator 23:25:54,758 INFO -Configuration Result: [Success] Name QuartzTopShelfDemoService [Success] DisplayName QuartzTopShelfDemo服務 [Success] Description Quartz+TopShelf實現Windows服務作業調度的一個示例Demo [Success] ServiceName QuartzTopShelfDemoService 23:25:54,772 INFO -Topshelf v3.3.154.0, .NET Framework v4.0.30319.34014 23:25:54,781 DEBUG-Attempting to install 'QuartzTopShelfDemoService' 23:25:54,901 INFO -Installing QuartzTopShelfDemo服務 service 23:25:55,123 DEBUG-Opening Registry 23:25:55,123 DEBUG-Service path: "E:\DotNetProject\Y2016\QTDemo\QTDemo\bin\Release\QTDemo.exe" 23:25:55,123 DEBUG-Image path: "E:\DotNetProject\Y2016\QTDemo\QTDemo\bin\Release\QTDemo.exe" -displayname "QuartzTopShelfDemo服務" -servicename "QuartzTopShelfDemoService" 23:25:58,357 DEBUG-Closing Registry 23:28:10,442 INFO -Configuration Result: [Success] Name QuartzTopShelfDemoService [Success] DisplayName QuartzTopShelfDemo服務 [Success] Description Quartz+TopShelf實現Windows服務作業調度的一個示例Demo [Success] ServiceName QuartzTopShelfDemoService 23:28:10,455 INFO -Topshelf v3.3.154.0, .NET Framework v4.0.30319.34014 23:28:10,649 DEBUG-Started by the Windows services process 23:28:10,649 DEBUG-Running as a service, creating service host. 23:28:10,651 INFO -Starting as a Windows service 23:28:10,654 DEBUG-[Topshelf] Starting up as a windows service application 23:28:10,657 INFO -[Topshelf] Starting 23:28:10,658 DEBUG-[Topshelf] Current Directory: E:\DotNetProject\Y2016\QTDemo\QTDemo\bin\Release 23:28:10,658 DEBUG-[Topshelf] Arguments: 23:28:10,940 INFO -[Topshelf] Started 23:28:10,988 INFO -TestJob測試 23:28:15,000 INFO -TestJob測試 23:28:20,000 INFO -TestJob測試
附:源碼下載