【翻译 博主注释版】Quartz.NET - Quartz.NET快速入门

一. Quartz.NET快速入门

欢迎翻阅 Quartz.NET 快速入门。您将从此入门中获得如下详细内容:

  • 下载 Quartz.NET
  • 安装 Quartz.NET
  • 根据你需要的规则配置 Quartz
  • 启动示例程序

 二. 安装及下载

 你既可以下载 zip 文件,也可以使用 NuGet 包。Nuget 包只包含了运行 Quartz.NET 所需要的二进制文件(编译后的dll文件),而 zip 文件中包含了源码、Quartz.NET的服务器的示例代码。

1. 可以在网上搜索 Quartz.NET:

- 官网地址:https://www.quartz-scheduler.net/

2.然后点击 Download 即可下载:

- GitHub下载页面:https://github.com/quartznet/quartznet/releases

- 最新版 3.0.7

  • 一个是 zip 的 windows 版本
  • 一个是 tar.gz 的 Linux 版本

 3. 下载之后,zip中的内容:

 Zip归档

操作简述:下载了 Quartz.NET 之后,将其解压到某个地方,然后从 bin 目录中的获取 Quartz.dll 并使用它。

Quartz.NET 的核心类库不包含任何硬编码的依赖项。当你选择使用需要 JSON.NET 的 JSON 序列化包的时候,你可以加入更多依赖项。如要想要成功的运行 Quartz.NET,你至少在运用程序目录下放有 Quartz.dll。所以只需要将 Quartz.NET 作为一个引用添加到 Visual Studio 中并使用它们。你可以从 " bin\your-target-framework-version\release\Quartz " 路径的目录下的提取文件中找到这些 dll。

获取源码

1. 通过下载 zip 通过编译的方式

Tips:

  【1】 如果再打开的过程中出现:

" error  : 项目的默认 XML 命名空间必须为 MSBuild XML 命名空间。如果项目是用 MSBuild 2003 格式创建的,请将 xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 添加到 <Project> 元素中。如果项目是用旧的 1.0 或 1.2 格式创建的,请将其转换为 MSBuild 2003 格式。"

    这是说明 VS 需要 2017的版本才能打开,建议升级到 2017版本。

  【2】 在修改为 VS2017打开之后,如果出现以下问题:

那么要在 VS 的 " 工具 " -> " 选项... " 所打开的选项窗体中,选择 " Nuget 包管理器 " -> " 常规 " 选项中勾选 " 程序包还原 " 中的所有的选项:

  【3】在修复了【1】【2】问题之后,我们编译还是会有如下问题:

  此问题暂时还没有解决,这个博主在 GitHub 中已经问过 Quartz.NET 的作者了:

2. 通过 Git 下载,然后再进行编译的方法

【1】安装 Git,然后找一个文件夹,右键选择 " Git Bash Here "

【2】打开的窗体中,输入 " git clone git@github.com:quartznet/quartznet.git ",然后等待下载完成之后再输入 " .\build.cmd " 来执行下载的 Quartz.NET的代码下 build.cmd 批处理文件

git clone git@github.com:quartznet/quartznet.git
.\build.cmd

  【3】执行成功下载完成之后(图1),运行 build.cmd (图2),接着进入 VS 2017 就可以成功编译生成(图3)

图1

图2

图3


 三. NuGet包

 最简单的获取方式。只需要启动安装用 Nuget 的 Visual Studio,并且从 " Nuget 包管理器 " 中添加对 Quartz 的引用。

  • 右键单击项目引用,并从右键菜单中选择 " 管理 Nuget 程序包  " ...
  • 从左侧选择在线类别
  • 在右上方的搜索框中写入 " Quartz ",然后点击回车
  • 从搜索的结果中选择 " Quartz.NET ",然后点击安装
  • 完成!

或者,通过 NuGet 命令行:

Install-Package Quartz

如果你想要添加 JSON 序列化的内容,只需要用同样的方法添加 Quartz.Serialization.Json。


 四. 配置

这才是重点!Quarty.NET 是一个配置能力很强的类库。这里有三种方式(它们并不相互排斥)来提供 Quartz.NET 的配置信息:

  • 以编程的方式向调度工厂提供 NameValueCollection 的参数
  • 使用 quartz-element 通过标准的 youapp.exe.config 配置文件(适用于完整版的 .NET Framework)
  • 通过使用在你应用程序根目录下的 quartz.config (适用于 .NET Core 和完整的 .NET Framework)

你可以在 Quartz.NET 的 zip 文件中,找到这些所有选择项的例子。

可用的属性的完整的文档在《 Quartz Configuration Reference 》

 为了开始和快速运行,一个基本的 quartz.config 的部分内容看上去像这样:

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

记住,在 Visual Studio 文件属性页中,设置 " Copy to Output Directory " 的值为 " Copy always "。否则,如果配置不在构建目录中创建,那么将不能看到它。

 通过上面的配置创建的调度具有如下的特点:

  • quartz.scheduler.instance - 这个调度器的名称将会是 " 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)
        {
            // trigger async evaluation
            RunProgram().GetAwaiter().GetResult();
        }

        private static async Task RunProgram()
        {
            try
            {
                // Grab the Scheduler instance from the Factory
                NameValueCollection props = new NameValueCollection
                {
                    { "quartz.serializer.type", "binary" }
                };
                StdSchedulerFactory factory = new StdSchedulerFactory(props);
                IScheduler scheduler = await factory.GetScheduler();

                // and start it off
                await scheduler.Start();

                // some sleep to show what's happening
                await Task.Delay(TimeSpan.FromSeconds(60));

                // and last shut down the scheduler when you are ready to close your program
                await scheduler.Shutdown();
            }
            catch (SchedulerException se)
            {
                await Console.Error.WriteLineAsync(se.ToString());
            }
        }
    }
}

自从 Quartz 3.0 之后,当执行了 scheduler.Shutdown() 之后没有任何可执行代码的时候,应用程序终止,这是因为将不再会有任何活动的线程。如果希望调度程序在 Task.Delay 和 Shutdown 被执行之后,也能继续执行,则应该手动阻塞应用程序退出。

当前,运行上面的程序将不会显示任何信息。当10秒过去了之后,程序将会终止。让我们向程序控制台添加一些日志输出。


 六. 增加日志

 LibLog 可以配置为使用不同的日志框架,如 Log4Net、Nlog 和 Serilong。

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.

我们需要一个简单的测试作业来测试功能,让我们创建一个输出 " Greetings from HelloJob! " 到控制台的类 HelloJob。

public class HelloJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        await Console.Out.WriteLineAsync("Greetings from HelloJob!");
    }
}

接着我们做一些有趣的事情,你需要在 Task.Delay 之前,在 Start() 之后,编写下面的代码:

// define the job and tie it to our HelloJob class
IJobDetail job = JobBuilder.Create<HelloJob>()
    .WithIdentity("job1", "group1")
    .Build();

// Trigger the job to run now, and then repeat every 10 seconds
ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("trigger1", "group1")
    .StartNow()
    .WithSimpleSchedule(x => x
        .WithIntervalInSeconds(10)
        .RepeatForever())
    .Build();

// Tell quartz to schedule the job using our trigger
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("Press any key to close the application");
            Console.ReadKey();
        }

        private static async Task RunProgramRunExample()
        {
            try
            {
                // Grab the Scheduler instance from the Factory
                NameValueCollection props = new NameValueCollection
                {
                    { "quartz.serializer.type", "binary" }
                };
                StdSchedulerFactory factory = new StdSchedulerFactory(props);
                IScheduler scheduler = await factory.GetScheduler();

                // and start it off
                await scheduler.Start();

                // define the job and tie it to our HelloJob class
                IJobDetail job = JobBuilder.Create<HelloJob>()
                    .WithIdentity("job1", "group1")
                    .Build();

                // Trigger the job to run now, and then repeat every 10 seconds
                ITrigger trigger = TriggerBuilder.Create()
                    .WithIdentity("trigger1", "group1")
                    .StartNow()
                    .WithSimpleSchedule(x => x
                        .WithIntervalInSeconds(10)
                        .RepeatForever())
                    .Build();

                // Tell quartz to schedule the job using our trigger
                await scheduler.ScheduleJob(job, trigger);

                // some sleep to show what's happening
                await Task.Delay(TimeSpan.FromSeconds(60));

                // and last shut down the scheduler when you are ready to close your program
                await scheduler.Shutdown();
            }
            catch (SchedulerException se)
            {
                Console.WriteLine(se);
            }
        }

        // simple log provider to get something to the console
        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("Greetings from HelloJob!");
        }
    }
}

现在去探索一下 Quartz.NET 吧!你可以继续阅读教程

posted @ 2019-11-28 18:02  白い  阅读(754)  评论(0编辑  收藏  举报