一、前言

近期项目中遇到一些需求,需要定时写入数据库,定时刷新缓存的问题,因此需要引入任务调度机制。

我的选择是使用 Quartz.Net,使用的版本是 3.2.4

这里强调一点:3.x的版本与2.x的版本使用方式有一定的差别,需要注意一下!!!

什么是Quartz.NET? Quartz.NET官方文档

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

二、Quartz.Net机制图

三、.Net Core中引入Quartz

新建.Net Core 类库项目命名为 MCronJob

创建完成后引入Quartz.Net

在Package Manager Console输入如下命令 安装Quartz包

Install-Package Quartz

由Quartz.Net关系图可知,我们需要JobFactory和实际任务类HelloJob

创建 CronJobFactory 类并实现  IJobFactory接口 ------------------任务工厂

public class CronJobFactory : IJobFactory
{
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
throw new NotImplementedException();
} public void ReturnJob(IJob job)
{
throw new NotImplementedException();
}
}

这里打个问号?NewJob和ReturnJob两个方法用来做什么?---------我是伏笔①

创建HelloJob类并实现  IJob接口 ---------------------------自定义的实际任务

public class HelloJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
await Console.Out.WriteLineAsync($"{DateTime.Now:HH:mm:ss}--Hello World!");
}
}

有了任务工厂和任务,我们接下来实现具体的任务调度

新建SchedulerCenter类 ---------------------------------------------调度中心

public class SchedulerCenter
{
private readonly IJobFactory _jobFactory;
private readonly ISchedulerFactory _schedulerFactory;
private IScheduler _scheduler;
public SchedulerCenter(IJobFactory jobFactory, ISchedulerFactory schedulerFactory)
{
_jobFactory = jobFactory;
_schedulerFactory = schedulerFactory;
}
public async void StartScheduler()
{
//1、从工厂获取调度程序实例
_scheduler = await _schedulerFactory.GetScheduler(); // 替换默认工厂
//_scheduler.JobFactory = this._jobFactory; //2、打开调度器
await _scheduler.Start(); //3、定义作业详细信息并将其与HelloJob任务相关联
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("HelloJob", "HelloJobGroup")
.Build(); //4、配置触发条件:立即触发作业运行,然后每10秒重复一次
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("HelloJob", "HelloJobGroup")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(10)
.RepeatForever())
.Build(); //5、将作业与触发条件添加到调度实例并进行关联
await _scheduler.ScheduleJob(job, trigger);
}
public void StopScheduler()
{
_scheduler?.Shutdown(true).Wait(30000);
_scheduler = null;
}
}

SchedulerCenter 中定义了两个方法 StartScheduler(开启调度)和StopScheduler(停止调度)

StartScheduler方法中关于任务配置与官网相同,这里不再赘述 Quartz.Net官方配置

这里注掉了一段代码 替换默认工厂 ---------我是伏笔②

接下来我们要启动这个定时任务,在Startup类的ConfigureServices方法中进行注入

//注入调度中心
services.AddSingleton<SchedulerCenter>(); //注入Quartz任何工厂及调度工厂
services.AddSingleton<IJobFactory, CronJobFactory>();
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>(); //注入HelloJob
services.AddTransient<HelloJob>();

在Startup类的Configure方法中进行启动配置

//获取调度中心实例
var quartz = app.ApplicationServices.GetRequiredService<SchedulerCenter>(); lifetime.ApplicationStarted.Register(() =>
{
quartz.StartScheduler(); //项目启动后启动调度中心
}); lifetime.ApplicationStopped.Register(() =>
{
quartz.StopScheduler(); //项目停止后关闭调度中心
});

运行截图:

成功启动定时任务

其他方式启动定时任务: Net Core 官方使用方式

四、Job实现服务注入

HelloJob类中注入用户信息服务,输出用户信息,改动如下:

public class HelloJob : IJob
{
private readonly IUserInfoServices _userInfoServices;
public HelloJob(IUserInfoServices userInfoServices)
{
_userInfoServices = userInfoServices;
}
public async Task Execute(IJobExecutionContext context)
{
var userInfo = _userInfoServices.GetUserInfo();
await Console.Out.WriteLineAsync($"{DateTime.Now:HH:mm:ss}--姓名:{userInfo.UserName},年龄:{userInfo.Age},地址:{userInfo.Address}");
}
}

再次运行项目,等待了一段时间发现并没有我们想要的输出(这里折腾我好久。。。)

这时回看刚刚埋下的伏笔① ,IJobFactory接口中有两个方法,NewJob和ReturnJob,这俩个方法做什么用?

NewJob方法: 注解的大概意思是:当触发器触发时获取一个Job实例供调度器执行,那么如何获取的Job实例呢?

我们看下NewJob第一个参数 TriggerFiredBundle,转到TriggerFiredBundle定义,看其为我们提供了什么。

如上图所示:TriggerFiredBundle中可以获取到IJobDetail

IJobDetail中有JobType属性也就是我们定义的Job类型,我们要做的就是获取到Job实例

安装 Microsoft.AspNetCore.Antiforgery包

Install-Package Microsoft.AspNetCore.Antiforgery -Version 2.2.0

改动Job工厂类如下所示:

public class CronJobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider; public CronJobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
} public void ReturnJob(IJob job)
{
}
}

接着打开SchedulerCenter中 伏笔② 的注释:替换默认工厂

  // 替换默认工厂
_scheduler.JobFactory = this._jobFactory;

再次运行,用户服务成功调用

猜测:替换默认任务工厂后 IServiceProvider 取到的HelloJob是 ConfigureServices 中使用依赖注入的方式取到的实例,可取到UserInfoServices;

而未替换默认任务工厂取到的HelloJob并不能取到UserInfoServices,故HelloJob的Execute不能执行。

五、源码地址

gitee地址:https://gitee.com/sirius_machao/mweb-api

.Net Core 3.1浏览器后端服务(五) 引入定时任务Quartz.Net的更多相关文章

  1. .Net Core 3.1浏览器后端服务(一) Web API项目搭建

    一.前言 基于CefSharp开发的浏览器项目已有一段时间,考虑到后期数据维护需要Server端来管理,故开启新篇章搭建浏览器后端服务.该项目前期以梳理服务端知识为主,后期将配合CefSharp浏览器 ...

  2. .Net Core 3.1浏览器后端服务(三) Swagger引入与应用

    一.前言 前后端分离的软件开发方式已逐步成为互联网项目开发的业界标准,前后端分离带来了诸多好处的同时,也带来了一些弊端. 接口文档的维护就是其中之一,起初前后端约定文档规范,开发的很愉快,随着时间推移 ...

  3. .Net Core 3.1浏览器后端服务(四) 你眼中的依赖注入与我相同吗?

    一.前言 DI-Dependency Injection 依赖注入 IoC-Inversion of Control 控制反转 近几年这依赖注入. 控制反转已成为软件开发中不可或缺的一部分,那么该怎么 ...

  4. 容易被忽视的后端服务 chunked 性能问题

    容易被忽视的后端服务 chunked 性能问题 标签(空格分隔): springboot springmvc chunked 背景 spring boot 创建的默认 spring mvc 项目 集成 ...

  5. 快速新建简单的koa2后端服务

    既然前端工程化是基于NodeJS,那么选择NodeJs做前后端分离部署也是理所应当的.其实只需要实现静态资源和代理的话,用nginx才是最好的选择,用NodeJS是为了日后能进一步在服务端上实现自动构 ...

  6. [转]快速新建简单的koa2后端服务

    本文转自:https://blog.csdn.net/saucxs/article/details/83788259 既然前端工程化是基于NodeJS,那么选择NodeJs做前后端分离部署也是理所应当 ...

  7. Springboot & Mybatis 构建restful 服务五

    Springboot & Mybatis 构建restful 服务五 1 前置条件 成功执行完Springboot & Mybatis 构建restful 服务四 2 restful ...

  8. spring rest 容易被忽视的后端服务 chunked 性能问题

    spring boot 容易被忽视的后端服务 chunked 性能问题 标签(空格分隔): springboot springmvc chunked 作者:王清培(Plen wang) 沪江Java资 ...

  9. 微信后端服务架构及其过载控制系统DAGOR

    微信架构介绍   眼下的微信后端包含3000多个移动服务,包括即时消息.社交网络.移动支付和第三方授权.该平台每天收到的外部请求在10 ^10个至10^11个.每个这样的请求都会触发多得多的内部微服务 ...

随机推荐

  1. console.warn All In One

    console.warn All In One ️ FBI 警告 // console 简介 // consoleCtt: function () { // if (window.console &a ...

  2. VS Code Extension

    VS Code Extension https://code.visualstudio.com/api/get-started/your-first-extension xgqfrms 2012-20 ...

  3. React Native 三端同构

    React Native 三端同构 https://www.ibm.com/developerworks/cn/web/wa-universal-react-native/index.html rea ...

  4. script async / defer

    script async / defer preload / prefetch https://abc.xgqfrms.xyz/ https://javascript.info/script-asyn ...

  5. Vue 组件的通信方式都有哪些?

    说一下 Vue 组件的通信方式都有哪些?(父子组件,兄弟组件,多级嵌套组件等等) 一.父组件向子组件传值 二.子组件向父组件传值 三.兄弟组件传值 四.跨组件 一.父组件向子组件传值 1.1props ...

  6. .NET微服务最佳实践 eShopOnContainers

    本文翻译自微软Docs, 内嵌译者多年使用的参悟,如理解有误,请不吝赐教. 微软与社区专家合作,开发了功能齐全的云原生微服务示例应用eShopOnContainers. 该应用旨在展示使用.NET.D ...

  7. close() 和fluse()区别

    1.close()默认包含了一次flush()操作,关闭之后,就不能再写入了. 2.flush()刷新,flush()之后,可以接着写入. 3.缓冲区默认大小是8192字节,如果小于8192字节,不会 ...

  8. 基于3.X版本的脚手架创建VUE项目

    一.基于交互式命令行的方式,创建vue项目 1.命令:vue create 项目名称.项目名称必须是英文的.不要包含中文.特殊的字符和符号.在cmd中输入命令:vue create vue_proje ...

  9. 腾讯云Centos7.6开放端口及配置腾讯云安全组

    1:防火墙的开启.关闭.状态查询.设置开机自启.开机禁用命令 检查状态(1):firewall-cmd --state 检查状态(2):systemctl status firewalld.servi ...

  10. elasticsearch如何设计集群

    本文为博客园作者所写: 一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/ 在写本文时就在想,如果让你负责一个elasticsearch集群,从零开始,你会从哪些方面 ...