使用Quartz实现定时作业
该文章是系列文章 基于.netcore和abp框架如何让windows服务执行quartz定时作业 的其中一篇。
quartz是一个开源的作业调度框架,准确的称谓应该是 quartz.net
,它是java开源项目quartz scheduler的一部分。
关于quartz的功能可访问
nuget地址:https://www.nuget.org/packages/quartz/3.0.7/
github地址:
首先是对定义的myjobservice进行完善。
using system.threading.tasks; namespace demo.myjob { public class myjobservice { public async task startasync() { //操作逻辑 } public async task stopasync() { //操作逻辑 } public async task continueasync() { //操作逻辑 } public async task pauseasync() { //操作逻辑 } } }
完善之后的代码如下
using system.threading.tasks; using quartz; using quartz.impl; namespace demo.myjob { public class myjobservice { private readonly task<ischeduler> _defaultscheduler; private static ischeduler _scheduler; public myjobservice() { _defaultscheduler = stdschedulerfactory.getdefaultscheduler(); } public async task startasync() { _scheduler = await _defaultscheduler; await _scheduler.start(); } public async task stopasync() { await _scheduler.shutdown(); } public async task continueasync() { await _scheduler.resumeall(); } public async task pauseasync() { await _scheduler.pauseall(); } } }
ischeduler
是主要的接口,它由ischedulerfactory
生成,stdschedulerfactory
继承自ischedulerfactory
。stdschedulerfactory
获取配置的顺序是先从app.config查找quartz section,没找到就查找文件名为quartz.config
的配置,如果再没有,代码内置的有默认的配置项。
使用xml文件配置
quartz.config
的简略配置如下
quartz.scheduler.instancename = quartztest quartz.threadpool.threadcount = 10 quartz.plugin.xml.type = quartz.plugin.xml.xmlschedulingdataprocessorplugin, quartz.plugins quartz.plugin.xml.filenames = ~/quartz_jobs.xml
- quartz.scheduler.instancename - 此调度程序的名称将为“quartztest”,如果没配置,默认名称是“quartzscheduler”
- quartz.threadpool.threadcount - 最多可同时运行10个作业,如果现在有超过10个job需要执行的话,不会报错,但是将有job不能执行。
- quartz.plugin.xml.type和quartz.plugin.xml.filenames需要新加nuget包
quartz.plugins
,指定了配置job详情的xml文件,该文件与quartz.config
在同级目录下。
注意:新增了三个文件,分别是job_scheduling_data_2_0.xsd、quartz.config、quartz_jobs.xml,文件属性为如果较新则复制
。
quartz_jobs.xml示例
<?xml version="1.0" encoding="utf-8"?> <job-scheduling-data xmlns="http://quartznet.sourceforge.net/jobschedulingdata" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" version="2.0"> <processing-directives> <overwrite-existing-data>true</overwrite-existing-data> </processing-directives> <schedule> <job> <name>sayhellojob</name> <group>sayhellojobgroup</group> <description>sayhello</description> <job-type>demo.myjob.jobs.sayhellojob,demo.myjob</job-type> <durable>true</durable> <recover>false</recover> </job> <trigger> <cron> <name>sayhellojobtrigger</name> <group>sayhellojobgroup</group> <description>sayhello</description> <job-name>sayhellojob</job-name> <job-group>sayhellojobgroup</job-group> <start-time>2019-06-13t00:00:00+08:00</start-time> <cron-expression>0 30 1 * * ?</cron-expression> </cron> </trigger> </schedule> </job-scheduling-data>
job-type标识加载sayhellojob的名称,要指定正确不然报错。更多配置可以参考:quartz.tests.integration/xml/testdata
实现job
详细文档地址:
ischeduler.start(system.threading.cancellationtoken)
调用之后将启动实现的job,该job必须继承ijob
,执行的操作放在实现的execute
方法中,该方法标识了task,也就是说我们可以在execute
方法内调用同步方法或者异步方法。
using system; using system.threading.tasks; using quartz; namespace demo.myjob.jobs { class sayhellojob : ijob { public async task execute(ijobexecutioncontext context) { await task.run(() => { console.writeline("hello world to async!"); }); console.writeline("hello world!"); } } }