一、经常在项目会用到定时任务同步数据或更新缓存等操作,在很久以前我们可能经常会用一个多线程或timer来做定时任务,这样能实现比较简单轻量级的任务;对于任务多且都调用频率不一样的任务,我们都会用到Quartz.Net这个组件;

Quartz.NET是一个强大、开源、轻量的作业调度框架,你能够用它来为执行一个作业而创建简单的或复杂的作业调度。它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等

二、  接下来简单演示一下Quartz使用:

2.1  首先新建一个AspNet Core API 项目,通过nuget包管理器安装引用Quartz

2.2  新建一个模拟任务类UserInfoSyncjob 必须继承IJob接口

namespace QuartzDemo.Quarzs
{
public class UserInfoSyncjob : IJob
{ public Task Execute(IJobExecutionContext context)
{
return Task.Run(() =>
{
//.....
Console.WriteLine($"{DateTime.Now.ToString()}:开始执行同步第三方数据");
//....同步操作 });
}
}
}

2.2  声明一个启动类QuartzStartup,来控制任务启动关闭等方法

添加启动方法

   public async Task<string> Start()
{
//1、声明一个调度工厂
_schedulerFactory = new StdSchedulerFactory();
//2、通过调度工厂获得调度器
_scheduler = await _schedulerFactory.GetScheduler();
//3、开启调度器
await _scheduler.Start();
//4、创建一个触发器
var trigger = TriggerBuilder.Create()
.WithSimpleSchedule(x => x.WithIntervalInSeconds().RepeatForever())//每两秒执行一次
.Build();
//5、创建任务
var jobDetail = JobBuilder.Create<UserInfoSyncjob>()
.WithIdentity("job", "group")
.Build();
//6、将触发器和任务器绑定到调度器中
await _scheduler.ScheduleJob(jobDetail, trigger);
return await Task.FromResult("将触发器和任务器绑定到调度器中完成");
}

2.3  在网站启动完成时调用QuartzStartup的Start方法开启任务

先注入 Quartz调度类

添加网站启动开始方法

2.4、运行效果,运行之前将控制台开启(方便查看任务是否在执行,实际环境可写日志)

该调度任务完成,上方定义的触发器是2秒一次,所以该任务每隔2秒执行;(也可以通过配置文件,控制执行平率,cron表达式可以很好控制)

三、第二结简单演示了Quartz的基本用法,本文重点不是主要讲解Quartz的用法,上方只是为了没使用过Quartz的同行有个简单映像,如果想详细学习,博客园有很多类似的文章,也可以和我探讨一下!

本文重点是每个任务类怎么通过注入获取其他类的使用及参数配置类等等;

假如有这样一个需求,UserInfoSyncjob同步任务里面需要配置数据库连接参数和日志记录、缓存记录等,在之前我们可能通过配置类、日志类、缓存类以工厂形式单例创建获取。

在AspNet Core自带IOC容器框架,很多配置类、日志类、缓存类等等,在全局很多地方都会使用,我们现在做法就是把这些类注入到IOC容器中,如果需要的只需要从构造方法中获取;

我们都知道如果一个从构造方法中获取IOC容器里面的类型实例,必须该类型也要主要到IOC容器中,这样我们就要想办法把UserInfoSyncjob通过容器来创建生产;

通过源码发现在Quartz有一个默认的生成job的工厂类Quartz.Simpl.SimpleJobFactory

using System;
using Quartz.Logging;
using Quartz.Spi;
using Quartz.Util;
namespace Quartz.Simpl
{
/// <summary>
/// The default JobFactory used by Quartz - simply calls
/// <see cref="ObjectUtils.InstantiateType{T}" /> on the job class.
/// </summary>
/// <seealso cref="IJobFactory" />
/// <seealso cref="PropertySettingJobFactory" />
/// <author>James House</author>
/// <author>Marko Lahma (.NET)</author>
public class SimpleJobFactory : IJobFactory
{
private static readonly ILog log = LogProvider.GetLogger(typeof (SimpleJobFactory)); /// <summary>
/// Called by the scheduler at the time of the trigger firing, in order to
/// produce a <see cref="IJob" /> instance on which to call Execute.
/// </summary>
/// <remarks>
/// It should be extremely rare for this method to throw an exception -
/// basically only the case where there is no way at all to instantiate
/// and prepare the Job for execution. When the exception is thrown, the
/// Scheduler will move all triggers associated with the Job into the
/// <see cref="TriggerState.Error" /> state, which will require human
/// intervention (e.g. an application restart after fixing whatever
/// configuration problem led to the issue with instantiating the Job).
/// </remarks>
/// <param name="bundle">The TriggerFiredBundle from which the <see cref="IJobDetail" />
/// and other info relating to the trigger firing can be obtained.</param>
/// <param name="scheduler"></param>
/// <returns>the newly instantiated Job</returns>
/// <throws> SchedulerException if there is a problem instantiating the Job. </throws>
public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
IJobDetail jobDetail = bundle.JobDetail;
Type jobType = jobDetail.JobType;
try
{
if (log.IsDebugEnabled())
{
log.Debug($"Producing instance of Job '{jobDetail.Key}', class={jobType.FullName}");
} return ObjectUtils.InstantiateType<IJob>(jobType);
}
catch (Exception e)
{
SchedulerException se = new SchedulerException($"Problem instantiating class '{jobDetail.JobType.FullName}'", e);
throw se;
}
} /// <summary>
/// Allows the job factory to destroy/cleanup the job if needed.
/// No-op when using SimpleJobFactory.
/// </summary>
public virtual void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
disposable?.Dispose();
}
}
}

SimpleJobFactory 实现了IJobFactory接口,通过源码发现我们如果要替换该工厂来控制job的生成,只需要创建一个IOCJobFactory来替换默认job工厂就行

 

public class IOCJobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
public IOCJobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob; } public void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
disposable?.Dispose(); }
}

在调度任务类里面重新设置job工厂  _scheduler.JobFactory = _iocJobfactory;

在IOC中注入 UserInfoSyncjob、StdSchedulerFactory、IOCJobFactory    

 services.AddTransient<UserInfoSyncjob>();      // 这里使用瞬时依赖注入
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();//注册ISchedulerFactory的实例。
services.AddSingleton<QuartzStartup>();
services.AddSingleton<IJobFactory,IOCJobFactory>();

修改UserInfoSyncjob任务类,可以通过构造方法注入的方式从容器中拿到日志实现类、缓存类等等

 public class UserInfoSyncjob : IJob
{
private readonly ILogger<UserInfoSyncjob> _logger;
// private readonly ICache _cache;
public UserInfoSyncjob(ILogger<UserInfoSyncjob> logger)
{
//_cache = cache;
_logger = logger;// EnginContext.Current.Resolve<ILogger<UserInfoSyncjob>>();
}
public Task Execute(IJobExecutionContext context)
{
return Task.Run(() =>
{
//.....
// Console.WriteLine($"{DateTime.Now.ToString()}:开始执行同步第三方数据");
_logger.LogInformation ($"{DateTime.Now.ToString()}:开始执行同步第三方数据");
//....同步操作
// 我们都知道如果一个从构造方法中获取IOC容器里面的类型,必须该类型也要主要到IOC容器中; });
}
}

调整后运行截图

具体详细步骤请看源码:https://github.com/lxshwyan/QuartzDemo.git

 

  

AspNet Core结合Quartz使用定时任务且通过注入缓存或者配置参数的更多相关文章

  1. .net core+topshelf+quartz创建windows定时任务服务

    .net core+topshelf+quartz创建windows定时任务服务 准备工作 创建.net core 控制台应用程序,这里不做过多介绍 添加TopShelf包:TopShelf: 添加Q ...

  2. Spring Boot整合Quartz实现定时任务表配置

    最近有个小项目要做,spring mvc下的task设置一直不太灵活,因此在Spring Boot上想做到灵活的管理定时任务.需求就是,当项目启动的时候,如果有定时任务则加载进来,生成schedule ...

  3. .net core 基于 IHostedService 实现定时任务

    .net core 基于 IHostedService 实现定时任务 Intro 从 .net core 2.0 开始,开始引入 IHostedService,可以通过 IHostedService ...

  4. .NET Core开源Quartz.Net作业调度框架实战演练

    一.需求背景 人生苦短,我用.NET Core!作为一枚后端.NET开发人员,项目实践常遇到定时Job任务的工作,在Windows平台最容易想到的的思路Windows Service服务应用程序,而在 ...

  5. .NET Core 基于Quartz的UI可视化操作组件 GZY.Quartz.MUI 简介

    前言 最近在用Quartz做定时任务.虽然很方便,但是Quartz自己貌似是没有UI界面的..感觉操作起来 就很难受.. 查了一下,貌似有个UI组件 不过看了一下文档..直接给我劝退了..太麻烦了 我 ...

  6. SpringBoot定时任务 - 集成quartz实现定时任务(单实例和分布式两种方式)

    最为常用定时任务框架是Quartz,并且Spring也集成了Quartz的框架,Quartz不仅支持单实例方式还支持分布式方式.本文主要介绍Quartz,基础的Quartz的集成案例本,以及实现基于数 ...

  7. 【AspNet Core】Nuget代理网站

    因为访问Nuget太慢,在Dotnet Core RC2发布前,我就基于Asp.Net做了一个Nuget代理网站 这是网站地址:http://nuget.lzzy.net/ Nuget源:http:/ ...

  8. 使用Quartz创建定时任务

    项目开发中经常需要定时循环执行某些任务 比如定时发送报表,定时发送邮件,亦或者定时清理缓存,定时更新数据等等 有些时候可以简单地利用Windows Server的计划任务执行程序 Linux也有相应的 ...

  9. Quartz.net 定时任务之Cron表达式

    一.cron表达式简单介绍和下载 1.在上一篇博客"Quartz.net 定时任务之简单任务"中,我简单介绍了quartz的使用,而这篇博客我将介绍cron的具体使用(不足之处望大 ...

随机推荐

  1. python从入门到放弃之进程

    在理解进程之前我们先了解一下什么是进程的概念吧 以下就是我总结的一些基本的进程概念 进程就是正在运行的程序,它是操作系统中,资源分配的最小单位(通俗易懂点也就是电脑给程序分配的一定内存操作空间).资源 ...

  2. JMETER 用户变量作用域

    在编写JMETER 脚本时,我们会使用到变量,变量的作用域是线程. 我们通过下面的脚本验证一下变量的返回是线程. 1. 我们先定义一个amount的流程变量. 2.线程组使用三个线程 3.在线程组中添 ...

  3. 17、DNS服务器

    DNS     domain  name system   域名系统   [root@li ~]# vim /etc/nsswitch.conf hosts:      files dns --涉及到 ...

  4. Vuex操作步骤

    概念流程图: 案例: (1)src/store/index.js导出仓库 (2)在入口文件引入仓库并派发到每个组件,在入口文件main.js引入,挂载到根组件上,方便以后使用this.$store调用 ...

  5. 201871010104-陈园园 《面向对象程序设计(java)》第十四周学习总结

    201871010104-陈园园 <面向对象程序设计(java)>第十四周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ ...

  6. explain慢SQL分析解释

    使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是 如何处理你的SQL语句的.分析你的查询语句或是表结构的性能瓶颈. 使用方式:Explain+SQL语句 执行计划包含的信 ...

  7. 获取客户端IP地址的三个HTTP请求头的区别

    一.没有使用代理服务器的情况: REMOTE_ADDR = 您的 IP HTTP_VIA = 没数值或不显示 HTTP_X_FORWARDED_FOR = 没数值或不显示 二.使用透明代理服务器的情况 ...

  8. requests--会话对象,ssl验证

    会话对象 前面我们使用了添加cookie的方式来进行接口的访问,如果有几十个接口都要依赖登录,难道我们都要加上吗? Request的会话对象让你能够跨请求保持某些参数,它也会在同一请求Session实 ...

  9. map的基本操作

    向map添加元素: 因为map是不允许出现重复关键字的,所以如果重复插入键相同的元素后面的元素是不会插入成功的,下面是一个验证程序: #include<iostream> #include ...

  10. 图论问题(1) : hdu 1198

    题目转自hdu 1198,题目传送门 题目大意: 给你11种单位水管摆放位置,若上下或左右有水管连接则视为这两点相连. 最后让你求这些张图中有几个连通块. 解题思路: 本来觉得这道题很简单,不就一个建 ...