定時排程可以了解為定時執行某個方法或邏輯代碼,Timer也可以實作類似的功能。Quartz就是啟動定時任務的架構,直接在項目引用後就可以調用。
準備工作:
項目安裝Quartz
代碼實作:
1.聲明Scheduler(作業排程池)
2.聲明JobDetail
3.聲明Trigger
4.将JobDetail和Trigger添加到作業排程池中
下面是詳細的步驟:
項目引用Quartz,使用NuGet包管理器安裝,我安裝的Quartz是3.0.7版本(不同的版本,對應的api調用方式不一樣2.x和3.x差別挺大),對應的.NETFramework版本要求至少為4.5.2。
代碼實作部分:
1.Scheduler 作業排程器
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
await scheduler.Start();
2.JobBuilder 根據設定,生成一個詳細作業資訊(JobDetail)。(也就是具體要執行的邏輯代碼)
IJobDetail jobDetail1 = JobBuilder.Create<JobDemo>().WithIdentity("testjob", "group1").WithDescription("我是testjob").Build();
jobDetail1.JobDataMap.Add("name", "張三");
jobDetail1.JobDataMap.Add("age", "20");
3.TriggerBuilder 根據規則,生産對應的Trigger。(時間政策,什麼時候執行,執行間隔,執行次數等等)
//程式啟動2秒後執行,間隔3秒執行一次,一直執行
ITrigger trigger = TriggerBuilder.Create().WithIdentity("testtrigger", "group1").StartAt(new DateTimeOffset(DateTime.Now.AddSeconds(2)))
.WithCronSchedule("0/3 * * * * ?").WithDescription("我是testjob的觸發器").Build();
4.加入作業排程池中
await scheduler.ScheduleJob(jobDetail1, trigger);
完整代碼如下:
public async static Task Init()
{
try
{
Console.WriteLine("初始化scheduler.....");
//1.Scheduler 作業排程器
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
await scheduler.Start();
//2.JobBuilder 根據設定,生成一個詳細作業資訊(JobDetail)。
IJobDetail jobDetail1 = JobBuilder.Create<JobDemo>().WithIdentity("testjob", "group1").WithDescription("我是testjob").Build();
jobDetail1.JobDataMap.Add("name", "張三");
jobDetail1.JobDataMap.Add("age", "20");
//3.TriggerBuilder 根據規則,生産對應的Trigger
//程式啟動2秒後執行,間隔3秒執行一次,一直執行
ITrigger trigger = TriggerBuilder.Create().WithIdentity("testtrigger", "group1").StartAt(new DateTimeOffset(DateTime.Now.AddSeconds(2)))
.WithCronSchedule("0/3 * * * * ?").WithDescription("我是testjob的觸發器").Build();
//4.加入作業排程池中
await scheduler.ScheduleJob(jobDetail1, trigger);
Console.WriteLine("作業添加完成.....");
}
catch (Exception)
{
throw;
}
}
其中自定義邏輯是寫在第二步的JobDemo類中,代碼如下:
//IJob 作業接口,繼承并實作Execute, 編寫執行的具體作業邏輯。
public class JobDemo : IJob
{
public async Task Execute(IJobExecutionContext context)
{
try
{
await Task.Run(() =>
{
Console.WriteLine();
JobDataMap map = context.JobDetail.JobDataMap;
Console.WriteLine(map.Get("name"));
Console.WriteLine(map.Get("age"));
Console.WriteLine(DateTime.Now.ToString("r"));
Console.WriteLine();
});
}
catch (Exception)
{
throw;
}
}
}
以上代碼實作的邏輯是程式啟動2秒後開始列印在第二步中為jobDetail1添加的參數資訊。每隔3秒列印一次,隻要程式不停止,就一直執行。
如下所示:
用法的補充和擴充:
在第三步,建立Trigger,是為了控制程式運作的周期,運作次數等等
上面代碼示例中使用的是Cron表達式,詳細用法參考:https://www.cnblogs.com/sunjie9606/archive/2012/03/15/2397626.html
同時網上也有生成Cron表達式的工具,可以根據選擇的時間自動生成表達式:https://cron.qqe2.com/
除了Cron表達式外,還有另外的寫法來控制程式運作的周期,比如Simple模式。代碼如下:
//程式啟動立刻執行,間隔一秒執行一次,一共執行2+1次
ITrigger trigger = TriggerBuilder.Create().WithIdentity("testtrigger", "group1").StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(1).WithRepeatCount(2)).WithDescription("我是testjob的觸發器").Build();
這段代碼可以替換上面執行個體中第三部分的代碼,實作的邏輯是程式啟動後立刻執行任務,每隔一秒鐘執行一次,一共重複2次,加上剛開始執行的一次,一共會執行3次。
StartNow(),立即執行作業任務
WithIntervalInSeconds(1),一秒執行一次
WithRepeatCount(2),重複執行兩次,這裡也可以用RepeatForever(),表示永遠執行下去,不限制執行次數。
還有很多其他的api可以通過自行檢視,檢視方法如下:
關于監聽Listener
Quartz的監聽器用于當任務排程中所關注事件的發生時,能夠及時擷取這一事件的通知。類似于任務執行過程中郵件、短信類的提醒。Quartz監聽器主要有SchedulerListener、 TriggerListener、JobListener三種,分别表示排程器、觸發器、任務對應的監聽器。
三者使用方法類似。下面以TriggerListener為例,寫一個類說明用法:
MyTriggerListener類:
public class MyTriggerListener : ITriggerListener
{
public string Name => "MyTriggerListener";
public async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine("job完成時調用");
Console.WriteLine();
});
}
public async Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine("job執行時調用");
});
}
public async Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
{
await Task.Run(() =>
{
Console.WriteLine("錯過觸發時調用(例:線程不夠用的情況下)");
});
}
public async Task<bool> VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
//Trigger觸發後,job執行時調用本方法。true即否決,job後面不執行。
await Task.Run(() =>
{
Console.WriteLine("Trigger觸發後,job執行時調用本方法。");
});
return false;
}
}
自定義的MyTriggerListener實作後,需要添加監聽器到指定的trigger,如圖所示:
代碼:
scheduler.ListenerManager.AddTriggerListener(new MyTriggerListener());//添加TriggerListener
添加完成後,再次啟動項目,可以看到在控制台列印了相關資訊:
其他兩個監聽器用法類似。
關于監聽器可以參考下面連結,雖然是java版本的,但是很多東西是相同的,畢竟.Net的Quartz是由java版本變化而來。
https://www.cnblogs.com/mengrennwpu/p/7191229.html