一、经常在项目会用到定时任务同步数据或更新缓存等操作,在很久以前我们可能经常会用一个多线程或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. 4-1 Matplotlib 概述

      Matplotlib概述 In [1]: import numpy as np import matplotlib.pyplot as plt #pyplot是matplotlib的画图的接口   ...

  2. Rust中的枚举及模式匹配

    这个enum的用法,比c要强,和GO类似. enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> ...

  3. 201871010131-张兴盼《面向对象程序设计(java)》第十四周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业要求在哪里 https://www.cnblogs.com/lily-2018/p/1 ...

  4. springboot常见问题

    什么是 Spring Boot? 为什么要用 Spring Boot? Spring Boot 的核心配置文件有哪几个?它们的区别是什么? Spring Boot 的配置文件有哪几种格式?它们有什么区 ...

  5. (day44)前端、HTTP、HTML

    目录 一.什么是前端 二.web服务 (一)流程 (二)请求方式 (1)get请求 (2)post请求 三.HTTP协议 (一)什么是HTTP协议 (二)四大特性 (三)数据格式 (1)请求格式 (2 ...

  6. org.slf4j.helpers.Log4jLoggerFactory is not on classpath. Good!

    View Javadoc 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contrib ...

  7. 0x01 Wechall writeup

    目录 0x01 Wechall writeup Limited Access Training: Crypto - Caesar II Impossible n'est pas français Tr ...

  8. Linux学习笔记-第2天- 新的开始

    迟到且稀疏的笔记,希望自己今年会有所突破.加油

  9. gif转mp4

  10. requests--传递参数

    传递参数 传递URL参数 data = {'city': '北京'} # 参数有中文如果发送不了,必须要编码 city = parse.urlencode(data).encode('utf-8') ...