当我们在web开发中,常常会遇到这么一个需求,在后台执行某一项具体的任务,具体的说就是这些任务必须在后台定时执行。

Quartz.NET 是一个开源的 JAVA 移植版,它有着悠久的历史并且提供了强大的 Cron 表达式,这篇我们就来讨论如何在 ASP.NET Core 中使用 Quartz.NET 去执行一些后台任务。

安装 Quartz.NET

要想使用 Quartz.NET,你可以使用 Visual Studio 2019 中的 NuGet package manager 可视化界面进行安装,或者通过 NuGet package manager console 命令行输入如下命令:


Install-Package Quartz

Quartz.NET 中的Job,triggers 和 Schedulers

Quartz.NET 里有三个非常重要的概念:任务,触发器 和 调度器,对应着 Job,Trigger 和 Schedulers,Job 表示一个你需要被执行的任务,任务中可以写上你的业务逻辑代码,Job 就是一个实现了 IJob 接口的子类,如下代码所示:

class Job : IJob{public Task Execute(IJobExecutionContext context){throw new NotImplementedException();}}

Trigger 通常用于指定一个 job 是如何被调度的?什么意思呢?比如说:这个job是按天执行?还是按小时执行?还是按秒执行?值得注意的是因为支持了 Cron 表达式,还能够实现更加超级复杂的调度逻辑。

Scheduler 通常按照你预先设置的调度规则将 job 丢给它的任务队列,并按照 trigger 规则轮询然后执行任务。

创建 Scheduler

在 Quartz.NET 中可以创建多个 Scheduler,但为了演示目的我就创建一个 Scheduler 啦,下面的代码展示了如何去创建 Scheduler。


var scheduler = StdSchedulerFactory.GetDefaultScheduler().GetAwaiter().GetResult();

一旦使用上面的代码创建好了 Scheduler,接下来就可以将其作为服务注入到 Asp.net Core 的 IOC 容器中,实现代码如下:

public void ConfigureServices(IServiceCollection services){var scheduler = StdSchedulerFactory.GetDefaultScheduler().GetAwaiter().GetResult();services.AddSingleton(scheduler);services.AddRazorPages();}

开启和停止 scheduler

为了方便实现 开启停止 功能,我准备封装一个 hosting service 类,做法就是从 IHostingService 接口派生出一个 CustomQuartzHostedService 类,完整代码如下:


public class CustomQuartzHostedService : IHostedService
{private readonly IScheduler _scheduler;public CustomQuartzHostedService(IScheduler scheduler){_scheduler = scheduler;}public async Task StartAsync(CancellationToken cancellationToken){await _scheduler?.Start(cancellationToken);}public async Task StopAsync(CancellationToken cancellationToken){await _scheduler?.Shutdown(cancellationToken);}}

有了这个自定义类,接下来把这个类也注入到 servcies collection 中,实现代码如下:

public void ConfigureServices(IServiceCollection services){var scheduler = StdSchedulerFactory.GetDefaultScheduler().GetAwaiter().GetResult();services.AddSingleton(scheduler);services.AddHostedService<CustomQuartzHostedService>();services.AddRazorPages();}

创建 job

正如之前说到的,job 是一个实现了 IJob 接口 并且实现了 Execute() 的类,这个 Execute() 方法接收一个 IJobExecutionContext 参数。

下面的代码片段展示了这个 Job 类包含了一个异步方式的 Execute() 方法,这个方法中包含的代码就是你需要执行的业务逻辑。

[DisallowConcurrentExecution]public class NotificationJob : IJob{private readonly ILogger<NotificationJob> _logger;public NotificationJob(ILogger<NotificationJob> logger){_logger = logger;}public Task Execute(IJobExecutionContext context){_logger.LogInformation("Hello world!");return Task.CompletedTask;}}

创建 job 工厂

如果要定义一个 Job 工厂,则必须要实现 IJobFactory 接口中的 NewJob() 和 ReturnJob() 方法,下面的代码片段展示了如何去 创建 和 返回 job 的 factory 类。

public class CustomQuartzJobFactory : IJobFactory{private readonly IServiceProvider _serviceProvider;public CustomQuartzJobFactory(IServiceProvider serviceProvider){_serviceProvider = serviceProvider;}public IJob NewJob(TriggerFiredBundle triggerFiredBundle,IScheduler scheduler){var jobDetail = triggerFiredBundle.JobDetail;return (IJob)_serviceProvider.GetService(jobDetail.JobType);}public void ReturnJob(IJob job) { }}

值得注意的是,这里我并没有实现 job 池,如果你想实现这个功能,你需要修改以下 NewJob() 方法 并且重写 ReturnJob() 方法。

创建 JobMetadata 存储你的 job 元数据

我准备定义一个 JobMetadata 类去存储和job 相关联的元数据,比如说:job的id,job的name 等等,下面的代码展示了如何定义这么一个类。

public class JobMetadata{public Guid JobId { get; set; }public Type JobType { get; }public string JobName { get; }public string CronExpression { get; }public JobMetadata(Guid Id, Type jobType, string jobName,string cronExpression){JobId = Id;JobType = jobType;JobName = jobName;CronExpression = cronExpression;}}

使用 hosted service 封装 Scheduler 的start和stop

接下来,我需要丰富一下 CustomQuartzHostedService 类,完整的代码清单如下。

public class CustomQuartzHostedService : IHostedService{private readonly ISchedulerFactory schedulerFactory;private readonly IJobFactory jobFactory;private readonly JobMetadata jobMetadata;public CustomQuartzHostedService(ISchedulerFactory schedulerFactory,JobMetadata jobMetadata,IJobFactory jobFactory){this.schedulerFactory = schedulerFactory;this.jobMetadata = jobMetadata;this.jobFactory = jobFactory;}public IScheduler Scheduler { get; set; }public async Task StartAsync(CancellationToken cancellationToken){Scheduler = await schedulerFactory.GetScheduler();Scheduler.JobFactory = jobFactory;var job = CreateJob(jobMetadata);var trigger = CreateTrigger(jobMetadata);await Scheduler.ScheduleJob(job, trigger, cancellationToken);await Scheduler.Start(cancellationToken);}public async Task StopAsync(CancellationToken cancellationToken){await Scheduler?.Shutdown(cancellationToken);}private ITrigger CreateTrigger(JobMetadata jobMetadata){return TriggerBuilder.Create().WithIdentity(jobMetadata.JobId.ToString()).WithCronSchedule(jobMetadata.CronExpression).WithDescription($"{jobMetadata.JobName}").Build();}private IJobDetail CreateJob(JobMetadata jobMetadata){return JobBuilder.Create(jobMetadata.JobType).WithIdentity(jobMetadata.JobId.ToString()).WithDescription($"{jobMetadata.JobName}").Build();}}

接下来再看一下  Startup.ConfigureServices 方法下的完整代码。


public void ConfigureServices(IServiceCollection services)
{services.AddRazorPages();services.AddSingleton<IJobFactory, CustomQuartzJobFactory>();services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();services.AddSingleton<NotificationJob>();services.AddSingleton(new JobMetadata(Guid.NewGuid(), typeof(NotificationJob),"Notification Job", "0/10 * * * * ?"));services.AddHostedService<CustomQuartzHostedService>();
}   

这就是所有要做的事情,接下来运行应用程序,你会观察到 NotificationJob 的 Execute() 方法会每 10s 执行一次。

如何你的应用程序中需要有任务调用的功能,现在开始可以不需要使用Timer了,采用强大的 Quartz.NET 即可,而且还有一个????????的功能就是:你可以把 job 持久化到 SQL Server, PostgreSQL, SQLite 中,太强大了。

译文链接:https://www.infoworld.com/article/3529418/how-to-schedule-jobs-using-quartznet-in-aspnet-core.html

如何在 ASP.NET Core 中使用 Quartz.NET 执行任务调度相关推荐

  1. 如何在 ASP.NET Core 中使用 HttpClientFactory ?

    ASP.Net Core 是一个开源的,跨平台的,轻量级模块化框架,可用它来构建高性能的Web程序,这篇文章我们将会讨论如何在 ASP.Net Core 中使用 HttpClientFactory. ...

  2. 如何在 ASP.Net Core 中使用 Autofac

    依赖注入可以有效的实现对象之间的 松耦合 并能够实现代码的可测试和可维护性,ASP.Net Core 提供了一个极简版的容器实现对 依赖注入 的原生支持,然而内置的依赖注入容器相比成熟的 依赖注入容器 ...

  3. 如何在 ASP.Net Core 中使用 Lamar

    ASP.Net Core 自带了一个极简的 开箱即用 的依赖注入容器,实际上,你还可以使用第三方的 依赖注入容器 来替代它,依赖注入是一种设计模式,它能够有效的实现对象之间的解耦并有利于提高单元测试和 ...

  4. 如何在 ASP.Net Core 中使用 MediatR

    MediatR 是一个 中介者模式 的.NET开源实现, 中介者模式 管控了一组对象之间的相互通讯并有效的减少了对象之间错综复杂的相互依赖,在 中介者模式 中,一个对象不需要直接和另一个对象进行通讯, ...

  5. 如何在 ASP.Net Core 中对接 WCF

    在 REST API 出现之前,SOAP (Simple Object Access Protocol) 一直都是基于 web 的标准协议,虽然现在 REST 大行其道,但在平时开发中总会遇到对接第三 ...

  6. 如何在 ASP.Net Core 中使用 NCache

    虽然 ASP.Net Core 中缺少 Cache 对象,但它引入了三种不同的cache方式. 内存缓存 分布式缓存 Response缓存 Alachisoft 公司提供了一个开源项目 NCache, ...

  7. 如何在 ASP.Net Core 中使用 Configuration Provider

    ASP.NET Core 是一个开源的,跨平台的,精简的模块化框架,可用于构建高性能,可扩展的web应用程序, ASP.NET Core 中的数据配置常用 k-v 的形式存储,值得注意的是,新的数据配 ...

  8. 如何在 ASP.Net Core 中使用 Serilog

    记录日志的一个作用就是方便对应用程序进行跟踪和排错调查,在实际应用上都是引入 日志框架,但如果你的 日志文件 包含非结构化的数据,那么查询起来将是一个噩梦,所以需要在记录日志的时候采用结构化方式. 将 ...

  9. 如何在 ASP.NET Core 中使用 URL Rewriting 中间件

    URL rewriting 是根据预先配置好的一组规则去修改 request url,值得注意的是:URL Rewriting 的重写功能和 url 重定向 是两个概念,本篇我们就来讨论下如何在 AS ...

最新文章

  1. 带套属于安全行为吗_教师不管学生上课睡觉的行为,属于不负责任吗?建议收藏!...
  2. Matplotlib绘图库初探
  3. python 用if判断一个数是不是整数_Python基础教程07-函数和模块的使用
  4. 实战 Windows Server 2012 群集共享卷
  5. linux命令行学习游戏,如何在Linux命令行中下载GOG游戏
  6. Mysql千万级数据查询优化技巧
  7. Eclipse安装包 百度网盘
  8. 安装Office2010提示缺少MSXML版本6.10.1129.0的解决方法
  9. matlab在mac中好用吗,Matlab Mac版上手
  10. python操作系统存储管理作业答案_操作系统课后题答案一
  11. mysql外文文献中英文3千字_MySQL数据库管理外文中英文翻译文献.doc
  12. 美团点评 2019校园招聘 后台开发方向
  13. 自学3D游戏建模有哪些教材?自学难不难?能学成就业吗
  14. php怎么让页面下雪花,html5实现下雪效果的方法
  15. http 请求 405 错误,解决办法
  16. Win10 盘符更改后需要修改的
  17. 苏州技师学院计算机专业怎么样,苏州技师学院口碑怎么样
  18. python怎么变成动图_python可以做动图吗
  19. java1000到十10以内的加减法,【小学】 生成10以内的加减法
  20. 《数据结构课程设计》实验报告

热门文章

  1. 68.iOS设备尺寸及型号代码(iPhoneXR/XS)
  2. jQuary的相关动画效果
  3. linux下svn常用指令
  4. SqlServer和MySQL中存储过程out返回值处理C#代码
  5. PostgreSQL表的行数统计
  6. Linux操作系统下Sudo命令的使用方法说明
  7. 开发第一个Meeting App
  8. Windows 10的下一个更新将在您观看视频时隐藏通知
  9. 再译《A *路径搜索入门》之四
  10. Mahout的taste推荐系统里的几种Recommender分析