Quartz.NET是功能齐全的开源作业调度系统,可用于最小的应用程序到大型企业系统。

Quartz.NET具有三个主要概念:

  • job:运行的后台任务
  • trigger:控制后台任务运行的触发器。
  • scheduler:协调job和trigger

ASP.NET Core通过托管服务对运行“后台任务”具有良好的支持,托管服务在ASP.NET Core应用程序启动时启动,并在应用程序生存期内在后台运行,Quartz.NET版本3.2.0通过Quartz.Extensions.Hosting包引入了对该模式的直接支持,Quartz.Extensions.Hosting可以与ASP.NET Core应用程序一起使用,也可以与基于“通用主机”的工作程序服务一起使用。

虽然.NET Core可以创建“定时”后台服务(例如,每10分钟运行一次任务),但Quartz.NET提供了更为强大的解决方案, 通过使用Cron表达式,您可以确保任务在特定时间(例如,凌晨2:30)运行,或仅在特定的几天运行,或这些时间的任意组合。Quartz.NET还允许您以集群方式运行应用程序的多个实例,以便在任何时候都只能运行一个实例。

安装Quartz.NET

Quartz.NET是一个.NET Standard 2.0 NuGet软件包,所以大部分项目都是支持的,你可以运行安装命令,dotnet add package Quartz.Extensions.Hosting,或者在NNuget可视化安装,如果查看该项目的.csproj,应该是下边这样:

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<UserSecretsId>dotnet-QuartzWorkerService-9D4BFFBE-BE06-4490-AE8B-8AF1466778FD</UserSecretsId>
</PropertyGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.2.3" />
</ItemGroup>
</Project>

安装完成以后,这个包会自动安装 Quartz.NET包,接下来,我们需要在我们的应用程序中注册Quartz服务和Quartz 。

添加Quartz.NET hosted service

修改Program.cs,注册服务

public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
} public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// Add the required Quartz.NET services
services.AddQuartz(q =>
{
// Use a Scoped container to create jobs. I'll touch on this later
q.UseMicrosoftDependencyInjectionScopedJobFactory();
}); // Add the Quartz.NET hosted service services.AddQuartzHostedService(
q => q.WaitForJobsToComplete = true); // other config
});
}

UseMicrosoftDependencyInjectionScopedJobFactory(),这个地方告诉Quartz.NET注册一个IJobFactory,然后从DI容器中获取Job,这样也可以使用 Scoped 类型的服务。

WaitForJobsToComplete():当程序关闭时,此设置可确保Quartz.NET在退出之前等待Job正常结束。

如果现在运行您的应用程序,您将看到Quartz服务启动,并将有很多日志输出到控制台:

info: Quartz.Core.SchedulerSignalerImpl[0]
Initialized Scheduler Signaller of type: Quartz.Core.SchedulerSignalerImpl
info: Quartz.Core.QuartzScheduler[0]
Quartz Scheduler v.3.2.3.0 created.
info: Quartz.Core.QuartzScheduler[0]
JobFactory set to: Quartz.Simpl.MicrosoftDependencyInjectionJobFactory
info: Quartz.Simpl.RAMJobStore[0]
RAMJobStore initialized.
info: Quartz.Core.QuartzScheduler[0]
Scheduler meta-data: Quartz Scheduler (v3.2.3.0) 'QuartzScheduler' 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 10 threads.
Using job-store 'Quartz.Simpl.RAMJobStore' - which does not support persistence. and is not clustered. info: Quartz.Impl.StdSchedulerFactory[0]
Quartz scheduler 'QuartzScheduler' initialized
info: Quartz.Impl.StdSchedulerFactory[0]
Quartz scheduler version: 3.2.3.0
info: Quartz.Core.QuartzScheduler[0]
Scheduler QuartzScheduler_$_NON_CLUSTERED started.
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
...

现在,您已经将Quartz作为托管服务运行在您的应用程序中,但是现在还没有添加需要运行的Job。

创建一个IJob

这个地方我创建一个简单的服务,并且我可以从构造函数中获取服务。

using Microsoft.Extensions.Logging;
using Quartz;
using System.Threading.Tasks; [DisallowConcurrentExecution]
public class HelloWorldJob : IJob
{
private readonly ILogger<HelloWorldJob> _logger;
public HelloWorldJob(ILogger<HelloWorldJob> logger)
{
_logger = logger;
} public Task Execute(IJobExecutionContext context)
{
_logger.LogInformation("Hello world!");
return Task.CompletedTask;
}
}

我还用[DisallowConcurrentExecution]特性,防止Quartz.NET尝试同时运行同一个作业。

设置Job

这个地方通常使用Cron表达式,来设置job的执行时间。

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddQuartz(q =>
{
q.UseMicrosoftDependencyInjectionScopedJobFactory(); // Create a "key" for the job
var jobKey = new JobKey("HelloWorldJob"); // Register the job with the DI container
q.AddJob<HelloWorldJob>(opts => opts.WithIdentity(jobKey)); // Create a trigger for the job
q.AddTrigger(opts => opts
.ForJob(jobKey) // link to the HelloWorldJob
.WithIdentity("HelloWorldJob-trigger") // give the trigger a unique name
.WithCronSchedule("0/5 * * * * ?")); // run every 5 seconds });
services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
// ...
});

现在运行应用程序,您将看到和以前相同的启动消息,然后每隔5秒钟就会看到HelloWorldJob写入控制台的信息:

将配置提取到appsettings.json

一般情况,我们都不会把cron表达式写死在代码中,一般是设置在appsettings.json中

{
"Quartz": {
"HelloWorldJob": "0/5 * * * * ?"
}
}

为了更简单的注册服务,这个地方我简单做了一个封装,这样也更灵活。

public static class ServiceCollectionQuartzConfiguratorExtensions
{
public static void AddJobAndTrigger<T>(
this IServiceCollectionQuartzConfigurator quartz,
IConfiguration config)
where T : IJob
{
// Use the name of the IJob as the appsettings.json key
string jobName = typeof(T).Name; // Try and load the schedule from configuration
var configKey = $"Quartz:{jobName}";
var cronSchedule = config[configKey]; // Some minor validation
if (string.IsNullOrEmpty(cronSchedule))
{
throw new Exception($"No Quartz.NET Cron schedule found for job in configuration at {configKey}");
} // register the job as before
var jobKey = new JobKey(jobName);
quartz.AddJob<T>(opts => opts.WithIdentity(jobKey)); quartz.AddTrigger(opts => opts
.ForJob(jobKey)
.WithIdentity(jobName + "-trigger")
.WithCronSchedule(cronSchedule)); // use the schedule from configuration
}
}

然后修改Program.cs,然后使用扩展方法:

public class Program
{
public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddQuartz(q =>
{
q.UseMicrosoftDependencyInjectionScopedJobFactory(); // Register the job, loading the schedule from configuration
q.AddJobAndTrigger<HelloWorldJob>(hostContext.Configuration);
}); services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
});
}

再次运行该应用程序将提供相同的输出:Job每5秒输入一次信息。

原文作者: andrewlock

原文链接: https://andrewlock.net/using-quartz-net-with-asp-net-core-and-worker-services/

最后

欢迎扫码关注我们的公众号 【全球技术精选】,专注国外优秀博客的翻译和开源项目分享,也可以添加QQ群 897216102

在.NET Core 中使用Quartz.NET的更多相关文章

  1. .Net Core中使用Quartz.Net

    一.介绍 Quartz.Net是根据Java的Quartz用C#改写而来,最新的版本是3.0.6,源码在https://github.com/quartznet/quartznet.主要作用是做一些周 ...

  2. .Net Core中使用Quartz.Net Vue开即用的UI管理

    Quartz.NET Quartz.Net 定制UI维护了常用作业添加.删除.修改.停止.启动功能,直接使用cron表达式设置作业执行间隔,有完整的日志记录. Quartz.NET是一个功能齐全的开源 ...

  3. .net core中使用Quartz任务调度

    使用xml配置Quartz任务调度程序 1.Nuget Install-Package Quartz Install-Package Quartz.Plugins 2.站点根目录下加入文件quartz ...

  4. Asp.Net Core 中利用QuartzHostedService 实现 Quartz 注入依赖 (DI)

    QuartzHostedService  是一个用来在Asp.Net Core 中实现 Quartz 的任务注入依赖的nuget 包: 基本示例如下: using System; using Syst ...

  5. .NET Core中Quartz.NET的依赖注入

    目录 介绍 项目概况 创建配置文件 使用构造函数注入 使用选项模式 结论 介绍 Quartz.NET是一个方便的库,允许您通过实现IJob接口来安排重复任务.然而,它的局限性在于,默认情况下,它仅支持 ...

  6. 在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度

    在这篇文章中,我将介绍如何使用ASP.NET Core托管服务运行Quartz.NET作业.这样的好处是我们可以在应用程序启动和停止时很方便的来控制我们的Job的运行状态.接下来我将演示如何创建一个简 ...

  7. 项目中使用Quartz集群分享--转载

    项目中使用Quartz集群分享--转载 在公司分享了Quartz,发布出来,希望大家讨论补充. CRM使用Quartz集群分享  一:CRM对定时任务的依赖与问题  二:什么是quartz,如何使用, ...

  8. .NET Core 中的通用主机和后台服务

    简介 我们在做项目的时候, 往往要处理一些后台的任务. 一般是两种, 一种是不停的运行,比如消息队列的消费者.另一种是定时任务. 在.NET Framework + Windows环境里, 我们一般会 ...

  9. .NET Core中使用IHostedService结合队列执行定时任务

    最近遇到了这样的场景:每隔一段时间,需要在后台使用队列对一批数据进行业务处理. Quartz.NET是一种选择,在 .NET Core中,可以使用IHostedService执行后台定时任务.在本篇中 ...

  10. Core中使用Hangfire

    之前使用Quartz.Net,后来发现hangfire对Core的继承更加的好,而且自带管理后台,这就比前者好用太多了. 安装注册 安装 PM> Install-Package Hangfire ...

随机推荐

  1. Jquery自定义扩展方法(二)--HTML日历控件

    一.概述 研究了上节的Jquery自定义扩展方法,自己一直想做用jquery写一个小的插件,工作中也用到了用JQuery的日历插件,自己琢磨着去造个轮子--HTML5手机网页日历控件,废话不多说,先看 ...

  2. Java中new关键字和newInstance方法的区别

    在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法一个是关键字外,最主要的区别是创建对象的方式不同.newInstance()使用类加载机制,new是创建一 ...

  3. ubuntu12.04软件中心打开错误和 ubuntu 包管理之“:E: 读错误 - read (5: 输入/输出错误) E: 无法解析或打开软件包的列表或是状态文件。”的解决

    执行ubuntu软讲中心时打不开.老是崩溃,从终端也下载不了软件. 执行包管理的update或者search等等会报错: E: 读错误 - read (5: 输入/输出错误) E: 无法解析或打开软件 ...

  4. python连接redis文档001

    Installation redis-py requires a running Redis server. See Redis’s quickstart for installation instr ...

  5. Mysql中常用的函数汇总

    Mysql中常用的函数汇总: 一.数学函数abs(x) 返回x的绝对值bin(x) 返回x的二进制(oct返回八进制,hex返回十六进制)ceiling(x) 返回大于x的最小整数值exp(x) 返回 ...

  6. PHP获取客户端和服务器端IP(转)

    客户端的ip变量: $_SERVER['REMOTE_ADDR'] :客户端IP,也有可能是代理IP $_SERVER['HTTP_CLIENT_IP']:代理端的IP,可能存在,也可能伪造 $_SE ...

  7. 如何从零开始学习区块链技术——推荐从以太坊开发DApp开始

    很多人迷惑于区块链和以太坊,不知如何学习,本文简单说了一下学习的一些方法和资源. 一. 以太坊和区块链的关系 从区块链历史上来说,先诞生了比特币,当时并没有区块链这个技术和名词,然后业界从比特币中提取 ...

  8. linux——网络基础

    装完linux系统要对网络(ip地址,子网掩码,网关,DNS)进行配置,才能连接网络 一,开启网卡eth0 CentOS显示没有网卡(eth0) 2.设置静态IP vim /etc/sysconfig ...

  9. npm 模块化管理

    我们要使用 npm 进行包管理,首先我们得安装 npm,怎么安装?其实只要你安装了 node,那便相当于安装了 npm: node下载地址:http://nodejs.cn/download/ 由于 ...

  10. Python字符串格式化 (%操作符)

    在许多编程语言中都包含有格式化字符串的功能,比如C和Fortran语言中的格式化输入输出.Python中内置有对字符串进行格式化的操作%. 模板 格式化字符串时,Python使用一个字符串作为模板.模 ...