C# Quartz.NET實現動態改變作業調度周期


Quartz:Java編寫的開源的任務調度作業框架 類似Timer之類定時執行的功能,但是更強大

Quartz.NET:是把Quartz轉成C#  NuGet中可以直接下載對應類庫

官網:https://www.quartz-scheduler.net/

主要對象:

Job :工作,要執行的具體內容繼承IJob。此接口中只有一個方法:execute(IJobExecutionContext context) 
JobDetail:具體的可執行的調度程序,Job 是這個可執行程調度程序所要執行的內容
Trigger:調度參數的配置,什么時候去調 執行間隔。 
Scheduler:調度容器,一個調度容器中可以注冊多個 JobDetail 和 Trigger。當 Trigger 與 JobDetail 組合,就可以被 Scheduler 容器調度了。 
大體介紹:

static void Main(string[] args)
{
Task<IScheduler> task_scheduler = StdSchedulerFactory.GetDefaultScheduler();
IScheduler scheduler = task_scheduler.Result;

//ISchedulerFactory _SchedulerFactory = new StdSchedulerFactory();
//IScheduler scheduler = _SchedulerFactory.GetScheduler().Result;

/*
* 過程:
* 一.通過StdSchedulerFactory計划工廠對象創建調度計划Scheduler
* 二.創建Job對象,需要繼承IJob 實現執行方法
* 三.觸發對象,2種:間隔執行和定時執行
* 1.ITrigger:間隔執行
* 2.ICronTrigger:定時執行
* 四.將job對象和觸發對象傳入調度計划Scheduler 開始執行
*
*
*/
//job創建
IJobDetail job = JobBuilder.Create<SayHello>().WithIdentity("定時確認完成訂單").Build();

////創建簡單計時器
//ISimpleTrigger _SimpleTrigger = TriggerBuilder.Create()
// .WithSimpleSchedule(t => t //聲明定時
// .WithIntervalInSeconds(2) //5秒一次
// .RepeatForever()) //永遠執行
// .StartNow() //立即開始
// .Build() //創建
// as ISimpleTrigger;
////關聯job與計時器
//scheduler.ScheduleJob(job, _SimpleTrigger);
/*
* WithCronSchedule參數說明:
* 秒 分 時 某一天 月 周 年(可選參數,一般不用)
* 秒分的合法值為0-59,小時:0-23,日期(天):0-31[要注意不同的月份中的天數不同] 月:0-11[或JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC] 星期:1-7(1=星期日)或[SUN,MON,TUE,WED,THU,FRI,SAT] (程序員數數法。。 萬事0開始)( 涉及到星期最好用英文)
* 通配符{[, - * /]都可以使用、[L #]只能星期課額外使用、[L W]天數可額外使用}
* ',' 子條件
* '*' 代表任意值的所有
* '-' 代表一個時段
* '/' 代表值的增量
* 比如:分鍾域中放入'0/15' 表示【從0開始 每隔15分鍾】 '3/20'表示【從第3分鍾開始 每隔20分鍾】 等同【3,23,43】
* '?' 只能用在天數或者星期中 表示【沒有指定值,滿足所有】
* 'L' 只能用在天數或者星期中 表示【這個時段的最后一天】
* 比如:月份中 1月的31號 2月的28或者29號 反正最后一天,或者 4L:該月的最后一個周四 6L:該月的最后一個周四。
* 注意!星期中表示【周六 SAT(手動加粗)】
* 'W' 代表離給定日期最近的那個工作日
* 比如:天數設置為15W 表示【離本月15號最近的一個工作日】??
* 'LW'代表這個月最后一周的工作日 可以在日期使用 ?待測
* '#' 代表本月的第幾個工作日
* 比如:星期中設置6#3 當月的第三個周五(6是周五!)
*
* 過失觸發:
* withMisfireHandlingInstructionDoNothing--->misfireInstruction = 2
* ——不觸發立即執行
* ——等待下次Cron觸發頻率到達時刻開始按照Cron頻率依次執行
*
* withMisfireHandlingInstructionFireAndProceed--->misfireInstruction = 1
* ——以當前時間為觸發頻率立刻觸發一次執行
* ——然后按照Cron頻率依次執行
*
* withMisfireHandlingInstructionIgnoreMisfires--->misfireInstruction = -1
* ——以錯過的第一個頻率時間立刻開始執行
* ——重做錯過的所有頻率周期后
* ——當下一次觸發頻率發生時間大於當前時間后,再按照正常的Cron頻率依次執行
*
*
*
* 實例:
* "0 0/5 * * * ?" 每5分鍾
* "10 0/5 * * * ?" 這分鍾后 10 秒起, 每五分鍾
* "0 30 10-13 ? * WED,FRI" 每周三、周五的10點到13點的30分時 【每周三, 周五 10:30, 11:30, 12:30 和 13:30】
* "0 0/30 8-9 5,20 * ?" 每個月的5號、20號的8點9點之間 每半小時觸發一次 因為0開始 所以10點的時候不觸發【8:00, 8:30, 9:00 9:30 】
* "0 0-5 14 * * ?" 每天的14:00到14:05分每分鍾一次
* "0 10,44 14 ? 3 WED" 每年三月的周三14:10和14:44
* "0 15 10 ? * MON-FRI" 每周三到周五的10::15
* "0 15 10 ? * 6#3" 每個月第三個周五的10:15
*
* 生成表達式的網站:http://cron.qqe2.com/?tdsourcetag=s_pctim_aiomsg 小時模塊的增量有bug注意下 但大體不影響使用
*/
ICronTrigger _CronTrigger = TriggerBuilder.Create()
.WithIdentity("定時確認")
.WithCronSchedule("0/2 * * * * ?") //秒 分 時 某一天 月 周 年(可選參數)
.Build()
as ICronTrigger;
scheduler.ScheduleJob(job, _CronTrigger);


scheduler.Start();
Console.ReadLine();
}
}

public class SayHello : IJob
{
public async Task Execute(IJobExecutionContext context)
{
Console.WriteLine("Hello Wrold!");
}
}
 

 

實例:

1.創建job

public class SayHello : IJob
{
public static int ii = 0;
static string str = "服務1=Cron 5秒一次。Hello World==SayHello ";
public async Task Execute(IJobExecutionContext context)
{

if (ii == 1)
{
QuartzManage.ModifyJob(context.JobDetail, context.Trigger as ICronTrigger, "0/2 * * * * ?");
ii = 0;
str += ",周期已改變!!變成2秒一次 ";
}
Common.WriteLog(str + context.Scheduler.GetHashCode());
}
}

public class SayCZ : IJob
{
public async Task Execute(IJobExecutionContext context)
{
Common.WriteLog("服務2=Simple 3秒一次。Hello CZ==SayCZ " + context.Scheduler.GetHashCode());
}
}
2.Quartz管理類

public class QuartzManage
{
static Task<IScheduler> task_scheduler = StdSchedulerFactory.GetDefaultScheduler();
static IScheduler scheduler;
private static readonly object objlock = new object();
static QuartzManage()
{
if (scheduler == null)
{
lock (objlock)
{
if (scheduler == null)
scheduler = task_scheduler.Result;
}
}
}

/// <summary>
/// 以Simple開始一個工作
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <param name="simpleInterval"></param>
public static void StartJobWithSimple<T>(string name, Action<SimpleScheduleBuilder> simpleInterval) where T : IJob
{
IJobDetail job = JobBuilder.Create<T>().WithIdentity(name + "_job", name + "_group").Build();
ITrigger Simple = TriggerBuilder.Create().StartNow()
.WithSimpleSchedule(simpleInterval)
.Build() as ISimpleTrigger;

scheduler.ScheduleJob(job, Simple);
scheduler.Start();
}

/// <summary>
/// 以Cron開始一個工作
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <param name="CronExpression"></param>
public static void StartJobWithCron<T>(string name, string CronExpression) where T : IJob
{

IJobDetail job = JobBuilder.Create<T>().WithIdentity(name + "_job", name + "_group").Build();

ITrigger CronTrigger = TriggerBuilder.Create().StartNow().WithIdentity(name + "_trigger", name + "_group")
.WithCronSchedule(CronExpression, w => w.WithMisfireHandlingInstructionDoNothing())
.Build() as ICronTrigger;

scheduler.ScheduleJob(job, CronTrigger);
scheduler.Start();
}

/// <summary>
/// Cron修改頻率
/// </summary>
/// <param name="job"></param>
/// <param name="trigger"></param>
/// <param name="CronExpression"></param>
public static void ModifyJob(IJobDetail job, ICronTrigger trigger, string CronExpression)
{
ICronTrigger _ICronTrigger = trigger;
_ICronTrigger.CronExpressionString = CronExpression;

scheduler.RescheduleJob(trigger.Key, _ICronTrigger);
}

/// <summary>
/// Simple修改頻率
/// </summary>
/// <param name="job"></param>
/// <param name="trigger"></param>
/// <param name="SimpleTime"></param>
public static void ModifyJob(IJobDetail job, ISimpleTrigger trigger, TimeSpan SimpleTime)
{
ISimpleTrigger _ISimpleTrigger = trigger;
_ISimpleTrigger.RepeatInterval = SimpleTime;

scheduler.RescheduleJob(trigger.Key, _ISimpleTrigger);
}

}
3.執行調度,並改變周期

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}


/// <summary>
/// Cron
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
QuartzManage.StartJobWithCron<SayHello>("first", "0/5 * * * * ?");
}

/// <summary>
/// Simple運行
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
QuartzManage.StartJobWithSimple<SayCZ>("second", x => x.WithIntervalInSeconds(3).RepeatForever()); //每三秒 一直執行
}

private void button3_Click(object sender, EventArgs e)
{
SayHello.ii = 1;
}
}
執行結果:

 

改變周期后 會有一個過時觸發的問題 根據設置不同的模式 執行的效果不同 misfire的概念,第一個代碼塊中有詳細注釋說明


免責聲明!

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



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