QuartzNet 任務管理系統


最近有面試!都有問道Quartz方面的問題,之前的項目有使用過,也知道怎么用,但面試時要說出它的原理,一時半會還真說不來!查閱了一些資料先記錄下來吧

 

Quartz.NET官網地址:https://www.quartz-scheduler.net/

Quartz.NET文檔地址:

https://www.quartz-scheduler.net/documentation/index.html

Quartz.NET是一個開源的作業調度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#寫成,可用於winform和asp.net應用中。

它提供了巨大的靈活性而不犧牲簡單性。你能夠用它來為執行一個作業而創建簡單的或復雜的調度。它有很多特征,如:數據庫支持,集群,插件,支持cron-like表達式等等

現在Quartz.NET3.0已支持Asp.Net Core,3.0新功能如下:

新功能

  • 具有異步/等待支持的基於任務的作業,內部以異步/等待方式工作

  • 支持.NET Core / netstandard 2.0和.NET Framework 4.5.2及更高版本

  • 通過提供程序名稱SQLite-Microsoft支持Microsoft.Data.Sqlite,舊的提供程序SQLite也仍然有效

  • 增加了SQL Server內存優化表和

    Quartz.Impl.AdoJobStore.UpdateLockRowSemaphoreMOT的初步支持

  • Common.Logging從相關性中刪除

  • 從ILMerge進程中刪除的C5集合不再需要

  • 在插件啟動時添加對作業調度XML文件的急切驗證的支持

  • 在TimeZoneUtil中添加對額外的自定義時區解析器功能的支持

變化

  • 作業和插件現在位於獨立的程序集NuGet包Quartz.Jobs和Quartz.Plugins中

  • ADO.NET提供者名稱已被簡化,提供者名稱沒有版本,例如SqlServer-20 => SqlServer

  • API方法已被重新使用,主要使用IReadOnlyCollection,這隱藏了兩個HashSets和List小號

  • LibLog一直隱藏於內部(ILog等),就像它原本打算的那樣

  • SimpleThreadPool消失了,舊的擁有的線程消失了

  • 調度程序方法已更改為基於任務,請記住等待它們

  • IJob接口現在返回一個任務\

  • 一些IList屬性已更改為IReadOnlyList以正確反映意圖

  • SQL Server CE支持已被刪除

  • DailyCalendar現在將日期時間用於排除的日期,並具有ISet接口來訪問它們

  • IObjectSerializer有新的方法,void Initialize(),必須實現

  • IInterruptableJob取消了上下文的CancellationToken

Quartz API的關鍵接口和類是:

  • IScheduler - 與調度程序交互的主要API。

  • IJob - 您希望由調度程序執行的組件實現的接口。

  • IJobDetail - 用於定義作業的實例。

  • ITrigger - 定義執行給定Job的時間表的組件。

  • JobBuilder - 用於定義/構建定義作業實例的JobDetail實例。

  • TriggerBuilder - 用於定義/構建觸發器實例

一、Quartz.NET基本使用

1、新建Asp.Net Core 項目,使用NuGet添加Quartz,或使用程序包管理器引用,命令如下:

Install-Package Quartz

2、簡單實例,代碼如下:

using Five.QuartzNetJob.ExecuteJobTask.Service;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Threading.Tasks;

namespace Five.QuartzNetJob.Web.Controllers
{
    public class TestTask
    {
        public async Task StartTestAsync() 
        {
            try
            {
                // 從工廠中獲取調度程序實例
                NameValueCollection props = new NameValueCollection
                {
                    { "quartz.serializer.type", "binary" }
                };
                StdSchedulerFactory factory = new StdSchedulerFactory(props);
                IScheduler scheduler = await factory.GetScheduler();
               
                // 開啟調度器
                await scheduler.Start();

                // 定義這個工作,並將其綁定到我們的IJob實現類
                IJobDetail job = JobBuilder.Create<HelloJob>()
                    .WithIdentity("job1", "group1")
                    .Build();

                // 觸發作業立即運行,然后每10秒重復一次,無限循環
                ITrigger trigger = TriggerBuilder.Create()
                    .WithIdentity("trigger1", "group1")
                    .StartNow()
                    .WithSimpleSchedule(x => x
                        .WithIntervalInSeconds(10)
                        .RepeatForever())
                    .Build();

                // 告訴Quartz使用我們的觸發器來安排作業
                await scheduler.ScheduleJob(job, trigger);

                // 等待60秒
                await Task.Delay(TimeSpan.FromSeconds(60));

                // 關閉調度程序
                await scheduler.Shutdown();
            }
            catch (SchedulerException se)
            {
                await Console.Error.WriteLineAsync(se.ToString());
            }
        }
    }
}

HelloJob內容如下:

using Quartz;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Five.QuartzNetJob.ExecuteJobTask.Service
{
    public class HelloJob : IJob
    {
        public  Task Execute(IJobExecutionContext context)
        {
             Console.Out.WriteLineAsync("Greetings from HelloJob!");
            return Task.CompletedTask;
        }
    }
}

執行效果如下:

 

注:Quartz的版本3.0.3中刪除了IJob實現的異地調用,也就是不支持async、await異步調用,3.0.2版本支持異步調用。

 

二、觸發器類型

 1、SimpleTrigger觸發器(簡單觸發器)

SimpleTrigger的屬性包括:開始時間和結束時間,重復計數和重復間隔。重復計數可以是零,一個正整數或常數值SimpleTrigger.RepeatIndefinitely。重復時間間隔屬性必須是TimeSpan.Zero或正的TimeSpan值。請注意,重復間隔為0會導致觸發器的“重復計數”觸發同時發生。

SimpleTrigger實例使用TriggerBuilder(用於觸發器的主屬性)和WithSimpleSchedule擴展方法(用於SimpleTrigger特定的屬性)構建。

在特定的時間內建立觸發器,無需重復,代碼如下:

 

// 觸發器構建器默認創建一個簡單的觸發器,實際上返回一個ITrigger
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create()
    .WithIdentity("trigger1", "group1")
    .StartAt(DateTime.Now) //指定開始時間為當前系統時間
    .ForJob("job1", "group1") //通過JobKey識別作業
    .Build();

在特定的時間建立觸發器,然后每十秒鍾重復十次:

 

// 觸發器構建器默認創建一個簡單的觸發器,實際上返回一個ITrigger
ITrigger trigger = trigger = TriggerBuilder.Create()
   .WithIdentity("trigger2", "group2")
   .StartAt(DateTime.Now) // 指定開始時間
   .WithSimpleSchedule(x => x
   .WithIntervalInSeconds(10)
   .WithRepeatCount(10)) // 請注意,重復10次將總共重復11次
   .ForJob("job2", "group2") //通過JobKey識別作業                   
   .Build();

構建一個觸發器,將在未來五分鍾內觸發一次:

 

// 觸發器構建器默認創建一個簡單的觸發器,實際上返回一個ITrigger
ITrigger trigger = trigger = (ISimpleTrigger)TriggerBuilder.Create()
   .WithIdentity("trigger3", "group3")
   .StartAt(DateBuilder.FutureDate(5, IntervalUnit.Minute)) //使用DateBuilder將來創建一個時間日期
   .ForJob("job3", "group3") //通過JobKey識別作業
   .Build();

建立一個現在立即觸發的觸發器,然后每隔五分鍾重復一次,直到22:00:

 

// 觸發器構建器默認創建一個簡單的觸發器,實際上返回一個ITrigger
ITrigger trigger = trigger = TriggerBuilder.Create()
   .WithIdentity("trigger4", "group4")
   .WithSimpleSchedule(x => x
        .WithIntervalInMinutes(5)//每5秒執行一次
        .RepeatForever())
   .EndAt(DateBuilder.DateOf(22, 0, 0))//晚上22點結束
   .Build();

建立一個觸發器,在一個小時后觸發,然后每2小時重復一次:

 

// 觸發器構建器默認創建一個簡單的觸發器,實際上返回一個ITrigger
ITrigger  trigger = TriggerBuilder.Create()
   .WithIdentity("trigger5") // 由於未指定組,因此“trigger5”將位於默認分組中
   .StartAt(DateBuilder.EvenHourDate(null)) // 獲取下個一小時時間                 
   .WithSimpleSchedule(x => x
        .WithIntervalInHours(2)//執行間隔2小時
        .RepeatForever())
   .Build(); 

因此簡單的任務調度使用SimpleTrigger完全夠用,如果SimpleTrigger還是不能滿足您的需求請往下看。

 

 2、CronTrigger觸發器

如果你需要一個基於類似日歷的概念而不是精確指定的SimpleTrigger時間間隔的工作調度計划,CronTriggers通常比SimpleTrigger更有用。

使用CronTrigger,您可以在每周一,周三的上午9點至上午10點之間指定開始時間表,例如“每星期五中午”或“每個工作日和上午9點30分”,或者“每5分鍾”和星期五”。

即使如此,就像SimpleTrigger一樣,CronTrigger有一個startTime,它指定了時間表的生效時間,還有一個(可選的)endTime,用於指定應該停止時間表的時間。

這里不在詳細介紹Cron。

Cron表達式在線生成器:http://cron.qqe2.com/

Cron表達式詳細介紹:https://www.jianshu.com/p/e9ce1a7e1ed1

 

 每天早上8點到下午5點建立一個觸發器,每隔一分鍾就會觸發一次:

// 觸發器構建器默認創建一個簡單的觸發器,實際上返回一個ITrigger
ITrigger trigger = TriggerBuilder.Create()
   .WithIdentity("Job1", "group1")
   .WithCronSchedule("0 0/2 8-17 * * ?")//使用Cron表達式
   .ForJob("Job1", "group1")
   .Build();

 

 建立一個觸發器,每天在上午10:42開始執行:

// 觸發器構建器默認創建一個簡單的觸發器,實際上返回一個ITrigger
ITrigger trigger = TriggerBuilder.Create()
   .WithIdentity("Job2", "group2")
   .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(10, 42)) // 在這里使用CronScheduleBuilder的靜態輔助方法
   .ForJob("Job2", "group2")
   .Build();

 

 構建一個觸發器,將在星期三上午10:42在除系統默認值之外的TimeZone中觸發:

// 觸發器構建器默認創建一個簡單的觸發器,實際上返回一個ITrigger
ITrigger trigger = TriggerBuilder.Create()
   .WithIdentity("Job3", "group3")
   .WithCronSchedule("0 42 10 ? * WED", x => x
   .InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time")))
   .ForJob("Job3", "group3")
   .Build();

 

總結: Quartz.NET的3.0版本跟之前的版本api接口變化並不大。只是在3.0版本中添加了異步調用,並支持.net core。簡單的任務調度使用官網中的實例即可滿足需求。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM