該文章是系列文章 基於.NetCore和ABP框架如何讓Windows服務執行Quartz定時作業 的其中一篇。
Quartz是一個開源的作業排程框架,準確的稱謂應該是 Quartz.Net
,它是Java開源專案Quartz Scheduler的一部分。
關於Quartz的功能可訪問 https://www.quartz-scheduler.net/features.html
nuget地址:https://www.nuget.org/packages/Quartz/3.0.7/
GitHub地址:https://github.com/quartznet/quartznet
首先是對定義的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
詳細文件地址:https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/index.html
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!");
}
}
}