Quartz.NET 3.x 入門


Quartz.NET是一個開源的作業調度框架,非常適合在平時的工作中,定時輪詢數據庫同步,定時郵件通知,定時處理數據等。Quartz.NET允許開發人員根據時間間隔(或天)來調度作業。它實現了作業和觸發器的多對多關係,還能把多個作業與不同的觸發器關聯。整合了 Quartz.NET的應用程序可以重用來自不同事件的作業,還可以爲一個事件組合多個作業。

官方學習文檔:http://www.quartz-scheduler.net/documentation/index.html
使用實例介紹:https://www.quartz-scheduler.net/documentation/quartz-3.x/quick-start.html
官方使用教程:Quartz.NET - Quartz.NET 3.x 教程
官方教程譯文:Quartz.NET 3.x 教程

Quartz.NET的快速入門指南

歡迎來到Quartz.NET的快速入門指南。當您閱讀本指南時,您將看到以下詳細信息:

  • 下載Quartz.NET
  • 安裝Quartz.NET
  • 根據您自己的特殊需要配置Quartz
  • 啓動示例應用程序

一、下載並安裝

您可以下載zip文件,也可以使用NuGet包。NuGet包只包含運行Quartz所需的二進制文件。zip文件附帶源代碼、示例和Quartz。NET服務器示例應用程序。

1、安裝包版本

簡約版:下載Quartz.NET,將其解壓縮到某個地方,從bin目錄獲取Quartz.dll和Common.Logging.dll並開始使用它們。

Quartz只依賴於稱爲Common的第三方庫。日誌(其中包含日誌抽象,允許您使用最適合您的日誌提供程序)。你需要在你的應用程序二進制文件旁邊有Quartz.dll和Commong.Logging.dll才能成功運行Quartz.NET。所以只需將它們作爲引用添加到使用它們的Visual Studio項目中。您可以從path bin\your-target-frame -version\release\Quartz中提取的歸檔文件中找到這些dll。

2、NuGet包安裝

只需啓動Visual Studio(使用NuGet安裝),並從包管理器擴展名中添加對包Quartz的引用:

  • 右鍵單擊項目的引用,並選擇Manage NuGet Packages…
  • 從左側選擇在線類別
  • 在右上角輸入Quartz,搜索並回車
  • 選擇Quartz.NET從搜索結果中點擊安裝
  • 完成了!

或從NuGet命令行:

Install-Package Quartz

如果您想添加JSON序列化,只需添加Quartz.Serialization.Json以同樣的方式打包。

3、Configuration 配置

這纔是重點!Quartz.NET是一個非常可配置的庫。提供Quartz有三種方式(它們並不相互排斥).NET配置信息:

  • 通過向調度器工廠提供NameValueCollection參數,以編程方式實現
  • 通過標準youapp.exe。配置配置文件使用quartz-element(完整的.net框架)
  • quartz.config在你的應用程序的根目錄下(適用於.net核心和完整的.net框架)

您可以在Quartz.NET zip文件中找到所有這些備選方案的示例。

基本的Quartz.config是這樣的:

quartz.scheduler.instanceName = MyScheduler
quartz.jobStore.type = Quartz.Simpl.RAMJobStore, Quartz
quartz.threadPool.threadCount = 3

記住將Visual Studio的文件屬性頁上的Copy設置爲Output目錄,以便始終保持Copy值。否則,如果配置不在構建目錄中,將看不到它。

該配置創建的調度器具有以下特點:

  • quartz.scheduler.instanceName —— 這個調度程序的名稱將是“MyScheduler”。
  • quartz.threadPool.threadCount —— 最多可以同時運行3個作業。
  • quartz.jobStore.type —— 所有Quartz的數據,例如作業和觸發器的詳細信息,都保存在內存中(而不是數據庫中)。即使您有一個數據庫,並且希望與Quartz一起使用它,我建議您在通過使用數據庫打開一個全新的維度之前,先讓Quartz與RamJobStore一起工作。

實際上你不需要定義這些屬性,如果你不想,Quartz.NET具有健全的默認設置

二、舉一個小例子

現在您已經下載並安裝了Quartz,接下來就可以啓動並運行示例應用程序了。下面的代碼獲得調度程序的一個實例,啓動它,然後關閉它:

Program.cs

using System;
using System.Threading.Tasks;

using Quartz;
using Quartz.Impl;

namespace QuartzSampleApp
{
    public class Program
    {
        private static void Main(string[] args)
        {
            // 觸發器異步計算
            RunProgram().GetAwaiter().GetResult();
        }

        private static async Task RunProgram()
        {
            try
            {
                // 從工廠獲取調度程序實例
                NameValueCollection props = new NameValueCollection
                {
                    { "quartz.serializer.type", "binary" }
                };
                StdSchedulerFactory factory = new StdSchedulerFactory(props);
                IScheduler scheduler = await factory.GetScheduler();

                // 然後開始
                await scheduler.Start();

                // 線程休眠60秒,是爲了更好的觀察
                await Task.Delay(TimeSpan.FromSeconds(60));

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

從Quartz 3.0開始,當scheduler. shutdown()之後沒有代碼可執行時,應用程序將終止,因爲不會有任何活動線程。如果您希望調度程序在任務完成後也能繼續運行,則應手動阻止退出應用程序。延遲和關機已經處理。

現在運行程序不會顯示任何內容。當10秒過去了,程序將會終止。讓我們向控制檯添加一些日誌記錄。

添加日誌記錄

LibLog可以配置爲使用不同的日誌框架;即Log4Net、NLog和Serilog。

當LibLog沒有檢測到任何其他日誌框架時,它將保持靜默。如果您還沒有準備好日誌框架,我們可以配置一個自定義日誌記錄器提供程序,它只記錄到控制檯並顯示輸出。

將下列代碼添加到 Program.cs

LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());

private class ConsoleLogProvider : ILogProvider
{
    public Logger GetLogger(string name)
    {
        return (level, func, exception, parameters) =>
        {
            if (level >= LogLevel.Info && func != null)
            {
                Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
            }
            return true;
        };
    }

    public IDisposable OpenNestedContext(string message)
    {
        throw new NotImplementedException();
    }

    public IDisposable OpenMappedContext(string key, string value)
    {
        throw new NotImplementedException();
    }
}

給程序添加調度任務

現在,我們應該得到更多的信息,當我們開始應用程序。

[12.51.10] [Info] Quartz.NET properties loaded from configuration file 'C:\QuartzSampleApp\quartz.config'
[12.51.10] [Info] Initialized Scheduler Signaller of type: Quartz.Core.SchedulerSignalerImpl
[12.51.10] [Info] Quartz Scheduler v.0.0.0.0 created.
[12.51.10] [Info] RAMJobStore initialized.
[12.51.10] [Info] Scheduler meta-data: Quartz Scheduler (v0.0.0.0) 'MyScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'Quartz.Core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'Quartz.Simpl.DefaultThreadPool' - with 3 threads.
  Using job-store 'Quartz.Simpl.RAMJobStore' - which does not support persistence. and is not clustered.

[12.51.10] [Info] Quartz scheduler 'MyScheduler' initialized
[12.51.10] [Info] Quartz scheduler version: 0.0.0.0
[12.51.10] [Info] Scheduler MyScheduler_$_NON_CLUSTERED started.

我們需要一個簡單的測試作業來測試功能,讓我們創建輸出問候到控制檯的HelloJob。

public class HelloJob : IJob
{
	public async Task Execute(IJobExecutionContext context)
	{
		await Console.Out.WriteLineAsync("來自HelloJob的問候!");
	}
}

您需要在Start()方法之後、在Task.Delay之前編寫代碼。

// 定義作業並將其綁定到HelloJob類
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);

完整的控制檯應用程序現在看起來是這樣的:

using System;
using System.Threading.Tasks;

using Quartz;
using Quartz.Impl;
using Quartz.Logging;

namespace QuartzSampleApp
{
    public class Program
    {
        private static void Main(string[] args)
        {
            LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());

            RunProgramRunExample().GetAwaiter().GetResult();

            Console.WriteLine("按任意鍵關閉應用程序");
            Console.ReadKey();
        }

        private static async Task RunProgramRunExample()
        {
            try
            {
                // 從工廠獲取調度程序實例
                NameValueCollection props = new NameValueCollection
                {
                    { "quartz.serializer.type", "binary" }
                };
                StdSchedulerFactory factory = new StdSchedulerFactory(props);
                IScheduler scheduler = await factory.GetScheduler();

                // 然後開始
                await scheduler.Start();

                // 定義作業並將其綁定到HelloJob類
                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)
            {
                Console.WriteLine(se);
            }
        }

        // 簡單的日誌提供程序來獲取控制檯的內容
        private class ConsoleLogProvider : ILogProvider
        {
            public Logger GetLogger(string name)
            {
                return (level, func, exception, parameters) =>
                {
                    if (level >= LogLevel.Info && func != null)
                    {
                        Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
                    }
                    return true;
                };
            }

            public IDisposable OpenNestedContext(string message)
            {
                throw new NotImplementedException();
            }

            public IDisposable OpenMappedContext(string key, string value)
            {
                throw new NotImplementedException();
            }
        }
    }

    public class HelloJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            await Console.Out.WriteLineAsync("來自 HelloJob 的問候!");
        }
    }
}

現在去探索一下Quartz.NET吧!您可以繼續閱讀教程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章