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. 在 ASP.NET Core和Worker Service中使用Quartz.Net

    现在有了一个官方包Quartz.Extensions.Hosting实现使用Quartz.Net运行后台任务,所以把Quartz.Net添加到ASP.NET Core或Worker Service要简 ...

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

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

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

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

随机推荐

  1. js上 十九、综合案例

    十九.综合案例 题目一: 封装一个函数equal(a1,a2),传入两个一维数组,判断两个数组是否包含相同的元素,如果相等,函数的返回值为true, 不相等,函数的返回值为false 1)例:arr1 ...

  2. [日常摸鱼]luogu1613跑路

    新年A的第一道题2333 https://www.luogu.org/problemnew/show/P1613 题意:给一张有向图,每条边长为1,每个单位时间只能走$2^k$的长度,$k$可以任意选 ...

  3. Linux OOM Killer造成数据库访问异常排查

    服务器上的服务器访问异常,查看/va/log/messages发现如下: Sep 22 16:08:21 safeserver kernel: java invoked oom-killer: gfp ...

  4. 手把手教你使用Python轻松搞定发邮件

    前言 现在生活节奏加快,人们之间交流方式也有了天差地别,为了更加便捷的交流沟通,电子邮件产生了,众所周知,电子邮件其实就是客户端和服务器端发送接受数据一样,他有一个发信和一个收信的功能,电子邮件的通信 ...

  5. Selenium Web元素操作

    我们定位到Web页面元素之后,可以对元素进行一系列的操作,实现跟页面的交互.包括点击.文本输入.元素属性获取等.常用的方法列举如下: 方法 描述 click() 点击元素 send_keys(**va ...

  6. 技术基础 | 用JSON在抖音上发布动态——使用Stargate即可轻松实现

    Cassandra是世界上经受住最多实战考验的数据库,通过其快速且易于使用的数据API,让你的程序开发升级. 本文将介绍什么是Stargate以及Stargate的最新进展,如果您想快速浏览相关代码和 ...

  7. 我的 2020:出书、办签售会、发展 VS Code 中文社区、成为开源先锋、全网 10 万粉丝、10 场演讲、内推 21 人、955.WLB 发扬光大

    感觉写 2019 年终总结还是在不久之前.转眼间,2020 已经接近尾声了.是时候来写写 2020 年的年终总结了. 出书 今年最高兴的事情之一,就是出了全球首本 VS Code 中文书 -- < ...

  8. Angular实战之使用NG-ZORRO创建一个企业级中后台框架(进阶篇)

    前言: 上一篇文章我们讲了如何在创建的Angular项目中快速引入ng-zorro-antd企业中台组件库,并且快速构建后台管理页面框架模板.这一章主要介绍的是如何在创建好的后台管理页面框架的快速生成 ...

  9. flowable中使用到的一些方法。获取人员部门信息

    package org.springblade.desk.utils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf ...

  10. IDEA 使用Git clone项目【建议】

    1.在启动页点击Get from Version Control进行克隆,这样可以减少不必要克隆Bug. 2.项目目录保持一致(保证文件的正确性),父级目录不要有其它任何文件(防止文件名冲突) 3.通 ...