Quartz.NET筆記整理,例項,動態改變週期排程。misfire、Cron
阿新 • • 發佈:2018-12-06
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的概念,第一個程式碼塊中有詳細註釋說明
程式碼例項: https://download.csdn.net/download/commandbaby/10664266