前言

在現代軟體開發中,排程任務是一個不可或缺的環節。無論是定期資料備份、報表產生、郵件發送,還是系統維護,都需要一個可靠的排程系統。Quartz.NET 就是一個強大的開源排程框架,它不僅提供了豐富的功能,還具備高度的靈活性和可靠性。

Scheduler Job Store Thread Pool Jobs Triggers Listeners Plugins

Quartz.NET 是什麼?

Quartz.NET 是 Java Quartz 排程框架的 .NET 移植版本,它提供了企業級的排程功能:

  • 支援複雜的排程模式(Cron表達式)
  • 具備叢集功能,確保高可用性
  • 提供任務持久化
  • 可靈活配置的錯誤處理機制
  • 豐富的監控與管理功能

基本概念

在開始使用 Quartz.NET 之前,我們需要理解幾個核心概念:

  1. Job (工作): 定義要執行的具體任務
  2. Trigger (觸發器): 決定任務何時執行
  3. Scheduler (排程器): 負責協調 Job 和 Trigger

實作範例

1. 基本設置

首先,使用 NuGet 安裝 Quartz 套件:

1
Install-Package Quartz

2. 建立簡單的 Job

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 定義一個簡單的工作
public class HelloJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
// 記錄工作執行時間
string executeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

// 執行工作邏輯
await Console.Out.WriteLineAsync($"Hello! 執行時間: {executeTime}");

// 可以從 context 取得傳入的參數
var dataMap = context.JobDetail.JobDataMap;
string jobSays = dataMap.GetString("jobSays");
await Console.Out.WriteLineAsync($"參數值: {jobSays}");
}
}

3. 設置觸發器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 建立排程器
IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler();

// 定義工作
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("helloJob", "group1") // 設定工作名稱和群組
.UsingJobData("jobSays", "Hello World!") // 傳入參數
.Build();

// 建立觸發器 - 每5秒執行一次
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1") // 設定觸發器名稱和群組
.StartNow() // 立即開始
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(5) // 間隔5秒
.RepeatForever()) // 永遠重複
.Build();

// 註冊工作和觸發器
await scheduler.ScheduleJob(job, trigger);

// 啟動排程器
await scheduler.Start();

4. 使用 Cron 表達式

Cron 表達式提供了更靈活的排程設定:

1
2
3
4
5
6
7
8
// 建立每天早上 9:00 執行的觸發器
ITrigger cronTrigger = TriggerBuilder.Create()
.WithIdentity("trigger2", "group1")
.WithCronSchedule("0 0 9 * * ?") // 每天早上 9:00
.Build();

// 註冊工作和觸發器
await scheduler.ScheduleJob(job, cronTrigger);

Cron 表達式說明:

  • 秒 分 時 日 月 星期 年
  • 0 0 9 * * ? = 每天早上 9:00:00 執行
  • 0 0/30 * * * ? = 每30分鐘執行一次
  • 0 0 9-17 * * ? = 每天早上9點到下午5點執行

5. 錯誤處理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ErrorHandlingJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
try
{
// 工作邏輯
await DoWork();
}
catch (Exception ex)
{
// 記錄錯誤
await LogError(ex);

// 決定是否重試
if (ShouldRetry(ex))
{
// 觸發重試機制
await TriggerRetry(context);
}

// 拋出例外,讓 Quartz 知道工作失敗
throw;
}
}
}

最佳實踐建議

  1. 工作設計原則

    • 保持工作的原子性
    • 避免長時間執行的工作
    • 實作適當的錯誤處理機制
  2. 效能考量

    • 適當設定執行緒池大小
    • 避免過於頻繁的排程
    • 考慮使用叢集來分散負載
  3. 監控與維護

    • 實作適當的記錄機制
    • 定期檢查工作執行狀態
    • 設置適當的警告機制

結語

Quartz.NET 是一個功能強大且靈活的排程框架,透過本文的介紹,相信您已經對它有了基本的認識。在實際應用中,建議根據專案需求選擇適當的功能組合,同時注意遵循最佳實踐原則,以建構出可靠的排程系統。

參考資源