Quartz.NET Windows
想必大家在项目中处理简单的后台持续任务或者定时触发任务的时候均使用 Thread 或者 Task 来完成,但是项目中的这种需求一旦多了的话就得将任务调度引入进来了,那今天就简单的介绍一下 Quartz.NET 基于 Windows 服务宿主是怎样配置使用的。
Quartz.NET 是一个优秀的任务调度框架,移植于 Java 版的 Quartz 。
示例环境
- .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 = 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 = ~/Conf/jobs.config

暂时需求需要修改的只有一处,看最后一行 quartz.plugin.xml.fileNames = ~/Conf/jobs.config 指定任务的配置文件路径。
2. 任务配置文件

1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- This file contains job definitions in schema version 2.0 format -->
3 <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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 节点)
| simple 节点项说明 | ||||
| 名称 | 类型 | 是否必填 | 默认值 | 描述 |
| name | string | Y | 触发器名称 | |
| group | string | N | 默认组名 | 触发器名称 |
| description | string | N | 触发器描述 | |
| job-name | string | Y | 要触发的任务的名称 | |
| job-group | string | Y | 要触发的任务的组名称 | |
| durable | boolean | N | false | 任务完成后是否依然保存到数据库 |
| recover | boolean | N | false | 应用或服务重启之后是否忽略过期任务 |
- 触发器 (trigger 节点)
下面说下最常用的两种触发器:
1)简单触发器(simple 节点)用于触发定时轮训执行的任务。
| simple 节点项说明 | ||||
| 名称 | 类型 | 是否必填 | 默认值 | 描述 |
| name | string | Y | 触发器名称 | |
| group | string | N | 默认组名 | 触发器名称 |
| description | string | N | 触发器描述 | |
| job-name | string | Y | 要触发的任务的名称 | |
| job-group | string | Y | 要触发的任务的组名称 | |
| repeat-count | int | Y | 0 | 重复次数(0:不执行;-1:不限次数) |
| repeat-interval | long | Y | 0 | 间隔时间(单位:毫秒) |
| start-time | date | N | 当前时间 | 开始时间 |
| end-time | date | N | 结束时间(如果不指定则一直执行直到重复次数) | |
2)Cron 触发器(cron 节点)根据 cron 表达式触发任务。
| cron 节点项说明 | ||||
| 名称 | 类型 | 是否必填 | 默认值 | 描述 |
| name | string | Y | 触发器名称 | |
| group | string | N | 默认组名 | 触发器名称 |
| description | string | N | 触发器描述 | |
| job-name | string | Y | 要触发的任务的名称 | |
| job-group | string | Y | 要触发的任务的组名称 | |
| cron | string | Y | 规则表达式 | |
| start-time | date | N | 当前时间 | 开始时间 |
| end-time | date | N | 结束时间 | |
注: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 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 #endregion
19
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 #endregion
34
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 IJob
12
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 the
19 /// JobExecutionContext before this method exits. The result itself
20 /// is meaningless to Quartz, but may be informative to
21 /// <see cref="T:Quartz.IJobListener" />s or
22 /// <see cref="T:Quartz.ITriggerListener" />s that are watching the job's
23 /// 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 #endregion
33 }
34 }

源码地址:https://github.com/Wlitsoft/QuartzNETWinServiceSample
推荐阅读:一个技术汪的开源梦
Quartz.NET Windows的更多相关文章
- .net core+topshelf+quartz创建windows定时任务服务
.net core+topshelf+quartz创建windows定时任务服务 准备工作 创建.net core 控制台应用程序,这里不做过多介绍 添加TopShelf包:TopShelf: 添加Q ...
- Quartz.NET Windows 服务示例
想必大家在项目中处理简单的后台持续任务或者定时触发任务的时候均使用 Thread 或者 Task 来完成,但是项目中的这种需求一旦多了的话就得将任务调度引入进来了,那今天就简单的介绍一下 Quartz ...
- Topshelf+Quartz实现windows任务
Topshelf使用示例, HostFactory.Run(x => { x.Service<QuartzStartup>(s => { s.ConstructUsing(na ...
- Quartz和TopShelf Windows服务作业调度
上一次写了一遍关于Quartz作业调度的文章 Quartz.NET 作业调度使用 现在使用TopShelf和Quartz实现windows服务作业调度 TopShelf版本4.0 Quartz版本3. ...
- 震惊!Windows Service服务和定时任务框架quartz之间原来是这种关系……
过场CG: 接到公司领导的文件指示,“小熊”需要在6月底去海外执行一个行动代号为[定时任务]的营救计划,这个计划关系到公司某个项目的生死(数据安全漏洞),作战部拟定两个作战方案: 方案一:使用务定 ...
- Python基础系列讲解-自动控制windows桌面
原链接:https://zhuanlan.zhihu.com/p/73001806 在使用PC时与PC交互的主要途径是看屏幕显示.听声音,点击鼠标和敲键盘等等.在自动化办公的趋势下,繁琐的工作可以让程 ...
- 从输入 URL 到浏览器接收的过程中发生了什么事情
从输入 URL 到浏览器接收的过程中发生了什么事情? 原文:http://www.codeceo.com/article/url-cpu-broswer.html 从触屏到 CPU 首先是「输入 U ...
- [python] PyMouse、PyKeyboard用python操作鼠标和键盘
1.PyUserInput 简介 PyUserInput是一个使用python的跨平台的操作鼠标和键盘的模块,非常方便使用.支持的平台及依赖如下: Linux - Xlib Mac - Quart ...
- Open Source
资源来源于http://www.cnblogs.com/Leo_wl/category/246424.html RabbitMQ 安装与使用 摘要: RabbitMQ 安装与使用 前言 吃多了拉就是队 ...
随机推荐
- JS常用的设计模式(14)—— 备忘录模式
备忘录模式在js中经常用于数据缓存. 比如一个分页控件, 从服务器获得某一页的数据后可以存入缓存.以后再翻回这一页的时候,可以直接使用缓存里的数据而无需再次请求服务器. 实现比较简单,伪代码: var ...
- hbase常用运维命令
一,基本命令: 建表:create 'testtable','coulmn1','coulmn2' 也可以建表时加coulmn的属性如:create 'testtable',{NAME => ' ...
- WeChat 6.3 wipe deleted chat messages as well as LINE 5.3 and above
Let me show you the WeChat version first. It is 6.3. What will happen to WeChat deleted chat message ...
- poj3349 哈希
这题目写了一上午,一直错,然后自己测试数据还都对.为什么呢,为什么呢,后来我才发现代码里有一行free(tmp)...在55行那里... #include <stdio.h> #inclu ...
- activiti搭建(三)整合Modeler
转载请注明源地址:http://www.cnblogs.com/lighten/p/5878169.html 接上一章,activiti工作流引擎虽然运行了起来,但是什么都没有.activiti官方在 ...
- Ninject在mvc中的简单配置
前言 Ninject是一款开源的轻量级的依赖注入插件.从接触ioc以来,一直都是使用这个,感觉用起来还是不错的,配置起来也很方便简单.在mvc中更是基本傻瓜式的配置. 开发前的准备 新建一个mvc3项 ...
- EXT格式误删除恢复
http://hatemysql.com/ 1.从/proc文件系统恢复数据#lsof |grep -i deletecat 11791 root 1w REG 253,0 94 1048589 /h ...
- GitHub 里面有大量优秀的第三方框架
写iOS 程序的时候往往需要很多第三方框架的支持,可以大大减少工作量,讲重点放在软件本身的逻辑实现上. GitHub 里面有大量优秀的第三方框架,而且 License 对商业很友好.一下摘录一下几乎每 ...
- BF算法和KMP算法(javascript版本)
var str="abcbababcbababcbababcabcbaba";//主串 var ts="bcabcbaba";//子串 function BF( ...
- AppSetting ,connectionStrings配置节
<appSettings> <!-- 当前使用的学校代码 --> <add key="DefaultCompanyID" value="cs ...