你的位置:首页 > ASP.net教程

[ASP.net教程]Quartz.NET Windows 服务示例

      想必大家在项目中处理简单的后台持续任务或者定时触发任务的时候均使用 Thread 或者 Task 来完成,但是项目中的这种需求一旦多了的话就得将任务调度引入进来了,那今天就简单的介绍一下 Quartz.NET 基于 Windows 服务宿主是怎样配置使用的。

Quartz.NET 是一个优秀的任务调度框架,移植于 Java 版的 Quartz 。

官网:http://www.quartz-scheduler.net

Github:https://github.com/quartznet/quartznet

示例环境

- .Net 4.5.2

- Quartz 2.4.1

- Common.Logging 3.3.1

- log4net 2.0.5

- Common.Logging.Log4Net1213 3.3.1

源码地址:https://github.com/Wlitsoft/QuartzNETWinServiceSample

配置

1. quartz.config

这个配置文件需要放在服务运行根目录下,用于指定 quartz 的一些运行配置,比如调度名称、线程池实现组件、线程池大小、任务配置文件路径等。

 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 = QuartzNETWinServiceScheduler 6  7 # configure thread pool info 8 quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz 9 quartz.threadPool.threadCount = 1010 quartz.threadPool.threadPriority = Normal11 12 # job initialization plugin handles our  without it defaults are used13 quartz.plugin. Quartz14 quartz.plugin.

暂时需求需要修改的只有一处,看最后一行 quartz.plugin.

2. 任务配置文件

 1 <??> 2 <!-- This file contains job definitions in schema version 2.0 format --> 3 <job-scheduling-data ="http://quartznet.sourceforge.net/JobSchedulingData" ="http://www.w3.org/2001/ version="2.0"> 4  5  <processing-directives> 6   <overwrite-existing-data>true</overwrite-existing-data> 7  </processing-directives> 8  9  <schedule>10   <job>11    <name>Job1</name>12    <group>Jobs</group>13    <description>任务1</description>14    <job-type>Wlitsoft.ProjectSample.QuartzNETWinService.Job.Job1,QuartzNETWinService</job-type>15    <durable>true</durable>16    <recover>false</recover>17   </job>18   <trigger>19    <simple>20     <name>Job1Trigger</name>21     <group>Jobs</group>22     <description>每 30 秒执行一次</description>23     <job-name>Job1</job-name>24     <job-group>Jobs</job-group>25     <repeat-count>-1</repeat-count>26     <repeat-interval>30000</repeat-interval>27    </simple>28   </trigger>29  </schedule>30 </job-scheduling-data>

以下为配置文件属性:

 - 任务 (job 节点)

job 节点项说明
名称类型是否必填默认值描述
namestringY 任务名称
groupstringN默认组名任务组名称
descriptionstringN 任务描述
job-typestringY 任务的类型全名称,一般实现 IJob 接口
durablebooleanNfalse任务完成后是否依然保存到数据库
recoverbooleanNfalse应用或服务重启之后是否忽略过期任务

 

 

  

 

 

 

 

- 触发器 (trigger 节点)

下面说下最常用的两种触发器:

1)简单触发器(simple 节点)用于触发定时轮训执行的任务。

simple 节点项说明
名称类型是否必填默认值描述
namestringY 触发器名称
groupstringN默认组名触发器名称
descriptionstringN 触发器描述
job-namestringY 要触发的任务的名称
job-groupstringY 要触发的任务的组名称
repeat-countintY0重复次数(0:不执行;-1:不限次数)
repeat-intervallongY0间隔时间(单位:毫秒)
start-timedateN当前时间开始时间
end-timedateN 结束时间(如果不指定则一直执行直到重复次数)

 

 

 

 

 

 

 

 

 

 

2)Cron 触发器(cron 节点)根据 cron 表达式触发任务。

cron 节点项说明
名称类型是否必填默认值描述
namestringY 触发器名称
groupstringN默认组名触发器名称
descriptionstringN 触发器描述
job-namestringY 要触发的任务的名称
job-groupstringY 要触发的任务的组名称
cronstringY 规则表达式
start-timedateN当前时间开始时间
end-timedateN 结束时间

 

 

 

 

 

 

 

 

 

注:cron 表达式在线生成:http://cron.qqe2.com

3. 日志配置文件

1) app.config

- configSctions 

1 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />2 <sectionGroup name="common">3    <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />4 </sectionGroup>

 

- commong.logging 配置

1 <common>2   <logging>3    <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1213">4     <arg key="configType" value="FILE-WATCH" />5     <arg key="configFile" value="~/Conf/log4net.config" />6     <arg key="level" value="INFO" />7    </factoryAdapter>8   </logging>9 </common>

 

    - configType : 用于指定日子配置文件类型,取值:INLINE - 在当前配置文件总;FILE-WATCH - 配置文件中。

    - configFile:配置文件路径。

    - level:日子输出级别。

- log4net 配置

 1 <??> 2 <configuration> 3  <configSections> 4   <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> 5  </configSections> 6  <log4net> 7  8   <logger name="job1" additivity="false" > 9    <level value="ALL" />10    <appender-ref ref="Job1TxtAppender" />11   </logger>12 13   <appender name="Job1TxtAppender" type="log4net.Appender.RollingFileAppender">14    <file value="log/job1.txt" />15    <appendToFile value="true" />16    <param name="MaxSizeRollBackups" value="10"/>17    <param name="MaximumFileSize" value="10240KB"/>18    <param name="RollingStyle" value="Size"/>19    <param name="StaticLogFileName" value="true"/>20    <layout type="log4net.Layout.PatternLayout">21     <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />22    </layout>23   </appender>24   25   <appender name="InfoFileAppender" type="log4net.Appender.RollingFileAppender">26    <file value="log/" />27    <appendToFile value="true" />28    <param name="DatePattern" value="yyyy-MM-dd'.txt'" />29    <rollingStyle value="Date" />30    <maxSizeRollBackups value="100" />31    <maximumFileSize value="1024KB" />32    <staticLogFileName value="false" />33    <Encoding value="UTF-8" />34    <filter type="log4net.Filter.LevelRangeFilter">35     <param name="LevelMin" value="INFO" />36     <param name="LevelMax" value="INFO" />37    </filter>38    <layout type="log4net.Layout.PatternLayout">39     <conversionPattern value="%date %-5level %logger - %message%newline" />40    </layout>41   </appender>42   <appender name="ErrorFileAppender" type="log4net.Appender.RollingFileAppender">43    <file value="log/error.txt" />44    <appendToFile value="true" />45    <rollingStyle value="Size" />46    <maxSizeRollBackups value="100" />47    <maximumFileSize value="10240KB" />48    <staticLogFileName value="true" />49    <Encoding value="UTF-8" />50    <filter type="log4net.Filter.LevelRangeFilter">51     <param name="LevelMin" value="WARN" />52     <param name="LevelMax" value="FATAL" />53    </filter>54    <layout type="log4net.Layout.PatternLayout">55     <conversionPattern value="%date %-5level %logger - %message%newline" />56    </layout>57   </appender>58   <root>59    <level value="INFO" />60    <appender-ref ref="InfoFileAppender" />61    <appender-ref ref="ErrorFileAppender" />62   </root>63  </log4net>64 65 </configuration>

log4net.config

 

主程序代码:

 1 using System.ServiceProcess; 2 using Common.Logging; 3 using Quartz; 4 using Quartz.Impl; 5  6 namespace Wlitsoft.ProjectSample.QuartzNETWinService 7 { 8   public partial class MainService : ServiceBase 9   {10     #region 私有属性11 12     //日志记录这。13     private readonly ILog _logger;14 15     //调度器。16     private readonly IScheduler _scheduler;17 18     #endregion19 20     #region 构造方法21 22     /// <summary>23     /// 初始化 <see cref="MainService"/> 类的新实例。24     /// </summary>25     public MainService()26     {27       InitializeComponent();28       this._logger = LogManager.GetLogger(this.GetType());29       StdSchedulerFactory factory = new StdSchedulerFactory();30       this._scheduler = factory.GetScheduler();31     }32 33     #endregion34 35     protected override void OnStart(string[] args)36     {37       this._scheduler.Start();38       this._logger.Info("服务启动");39     }40 41     protected override void OnStop()42     {43       if (!this._scheduler.IsShutdown)44         this._scheduler.Shutdown();45       this._logger.Info("服务停止");46     }47 48     protected override void OnPause()49     {50       this._scheduler.PauseAll();51       base.OnPause();52     }53 54     protected override void OnContinue()55     {56       this._scheduler.ResumeAll();57       base.OnContinue();58     }59   }60 }

 

示例任务代码:

 1 using Common.Logging; 2 using Quartz; 3  4 namespace Wlitsoft.ProjectSample.QuartzNETWinService.Job 5 { 6   public class Job1 : IJob 7   { 8     //日志构造者。 9     private static readonly ILog Logger = LogManager.GetLogger("job1");10 11     #region Implementation of IJob12 13     /// <summary>14     /// Called by the <see cref="T:Quartz.IScheduler" /> when a <see cref="T:Quartz.ITrigger" />15     /// fires that is associated with the <see cref="T:Quartz.IJob" />.16     /// </summary>17     /// <remarks>18     /// The implementation may wish to set a result object on the19     /// JobExecutionContext before this method exits. The result itself20     /// is meaningless to Quartz, but may be informative to21     /// <see cref="T:Quartz.IJobListener" />s or22     /// <see cref="T:Quartz.ITriggerListener" />s that are watching the job's23     /// execution.24     /// </remarks>25     /// <param name="context">The execution context.</param>26     public void Execute(IJobExecutionContext context)27     {28       string jobDes = context.JobDetail.Description;29       Logger.Info($"{jobDes}运行");30     }31 32     #endregion33   }34 }

源码地址:https://github.com/Wlitsoft/QuartzNETWinServiceSample 

推荐阅读:一个技术汪的开源梦