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吧!您可以继续阅读教程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值