搭建基于Quartz组件的定时调度任务

先在package包项目下,添加Quartz定时器组件:

新建类库项目Wsk.Core.QuartzNet,并且引用包类库项目。然后新建一个中间调度类,叫QuartzMiddleJob:

中间Job源码:

 public class QuartzMiddleJob : IJob
{
private readonly IServiceProvider _serviceProvider;
public QuartzMiddleJob(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task Execute(IJobExecutionContext context)
{
using (var scope = _serviceProvider.CreateScope())
{
var jobType = context.JobDetail.JobType;
var job = scope.ServiceProvider.GetRequiredService(jobType) as IJob;
await job.Execute(context);
}
}
}

新建一个Job工厂类,叫WeskyJobFactory,用来获取刚刚创建的中间调度类的服务:

新建一个通用执行计划类,叫WeskyJobSchedule,用于每次任务都通过该计划进行生成:

计划类和枚举源码:

 public class WeskyJobSchedule
{
public WeskyJobSchedule(Type jobType, string cronExpression)
{
this.JobType = jobType ?? throw new ArgumentNullException(nameof(jobType));
CronExpression = cronExpression ?? throw new ArgumentNullException(nameof(cronExpression));
}
/// <summary>
/// Job类型
/// </summary>
public Type JobType { get; private set; }
/// <summary>
/// Cron表达式
/// </summary>
public string CronExpression { get; private set; }
/// <summary>
/// Job状态
/// </summary>
public JobStatus JobStatu { get; set; } = JobStatus.Init;
} /// <summary>
/// 运行状态
/// </summary>
public enum JobStatus : byte
{
[Description("Initialization")]
Init = 0,
[Description("Running")]
Running = 1,
[Description("Scheduling")]
Scheduling = 2,
[Description("Stopped")]
Stopped = 3, }

现在添加一个任务,新建任务类 MyJobs,并且继承自IJob,然后在Excute方法里面,就是该任务执行调度时候会进去执行的了:

似乎上面哪儿感觉不太对,咱们把原来的Job工厂里面到代码稍微调整下如下:

NewJob源码:

 public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
}

现在新增一个静态类QuartzJobService,用来当做调度任务的中间启动项,并且把有关的一些服务注册进来:

对应源码:

  public static class QuartzJobService
{
public static void AddQuartzJobService(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
} services.AddSingleton<IJobFactory, WeskyJobFactory>();
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
services.AddSingleton<QuartzMiddleJob>(); services.AddSingleton<MyJobs>();
services.AddSingleton(
new WeskyJobSchedule(typeof(MyJobs), "0/1 * * * * ? ")
); services.AddHostedService<WeskyJobHostService>();
} }

最后,还少了个启动项,用来程序启动的时候,进行启动定时调度任务。新建类 WeskyJobHostService ,并且新建创建调度任务方法 CreateJob和触发器方法CreateTrigger:

然后,在开始和结束方法内:

以上源码如下:

  public class WeskyJobHostService: IHostedService
{
private readonly ISchedulerFactory _schedulerFactory;
private readonly IJobFactory _jobFactory;
private readonly IEnumerable<WeskyJobSchedule> _jobSchedules; public WeskyJobHostService(ISchedulerFactory schedulerFactory, IJobFactory jobFactory, IEnumerable<WeskyJobSchedule> jobSchedules)
{
_schedulerFactory = schedulerFactory ?? throw new ArgumentNullException(nameof(schedulerFactory));
_jobFactory = jobFactory ?? throw new ArgumentNullException(nameof(jobFactory));
_jobSchedules = jobSchedules ?? throw new ArgumentNullException(nameof(jobSchedules));
}
public IScheduler Scheduler { get; set; } public async Task StartAsync(CancellationToken cancellationToken)
{
Scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
Scheduler.JobFactory = _jobFactory;
foreach (var jobSchedule in _jobSchedules)
{
var job = CreateJob(jobSchedule);
var trigger = CreateTrigger(jobSchedule);
await Scheduler.ScheduleJob(job, trigger, cancellationToken);
jobSchedule.JobStatu = JobStatus.Scheduling;
}
await Scheduler.Start(cancellationToken);
foreach (var jobSchedule in _jobSchedules)
{
jobSchedule.JobStatu = JobStatus.Running;
}
} public async Task StopAsync(CancellationToken cancellationToken)
{
await Scheduler?.Shutdown(cancellationToken);
foreach (var jobSchedule in _jobSchedules)
{
jobSchedule.JobStatu = JobStatus.Stopped;
}
} private static IJobDetail CreateJob(WeskyJobSchedule schedule)
{
var jobType = schedule.JobType;
return JobBuilder
.Create(jobType)
.WithIdentity(jobType.FullName)
.WithDescription(jobType.Name)
.Build();
} private static ITrigger CreateTrigger(WeskyJobSchedule schedule)
{
return TriggerBuilder
.Create()
.WithIdentity($"{schedule.JobType.FullName}.trigger")
.WithCronSchedule(schedule.CronExpression)
.WithDescription(schedule.CronExpression)
.Build();
}
}

切回QuartzJobService,在 AddQuartzJobService 方法的最下方,添加上面启动服务的注册:

最后,在启动项目里面,添加对Wsk.CoreQuartz项目的引用,然后在WskService服务类下,添加对AddQuartzJobService服务的注册:

启动项目,看看效果:

由此可见,我们设置的每秒一次触发效果达成。为了检验是不是可以避免同一个调度任务产生并发,在调度任务方法里面,设置一个延时,看看效果:

运行结果:

说明在当前任务还没有完成的情况下,不会重复进入。如果要允许重复进,只需要把类上面的DisallowConcurrentExecution 标签注释掉就可以。

现在还原回去,然后在Cron表达式改写成定时10秒,看看效果:

运行结果:

以上就是本篇使用QuartzNet的全部内容,仅用于入门参考。对于其他定时用法、以及各种比较飘的使用,各位大佬可以自行变种。如果有什么建议或意见,也欢迎留言~~

十七、.net core(.NET 6)搭建基于Quartz组件的定时调度任务的更多相关文章

  1. springmvc+quartz简单实现定时调度

    一.简介:Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.Quartz可以用来创建简单或为运行十 ...

  2. 基于Azkaban的任务定时调度实践

    本文由云+社区发表 作者:maxluo 一.Azkaban介绍 Azkaban是LinkedIn开源的任务调度框架,类似于JavaEE中的JBPM和Activiti工作流框架. Azkaban功能和特 ...

  3. 基于Quartz实现简单的定时发送邮件

    一.什么是Quartz Quartz 是一个轻量级任务调度框架,只需要做些简单的配置就可以使用:它可以支持持久化的任务存储,即使是任务中断或服务重启后,仍可以继续运行.Quartz既可以做为独立的应用 ...

  4. 定时调度系列之Quartz.Net详解

    一. 背景 我们在日常开发中,可能你会遇到这样的需求:"每个月的3号给用户发信息,提醒用户XXX "."每天的0点需要统计前一天的考勤记录"."每个月 ...

  5. 定时调度篇之Quartz.Net详解(被替换)

    一. 背景 我们在日常开发中,可能你会遇到这样的需求:"每个月的3号给用户发信息,提醒用户XXX "."每天的0点需要统计前一天的考勤记录"."每个月 ...

  6. 定时调度系列之Quartz.Net详解(转)

    出处:https://www.cnblogs.com/yaopengfei/p/9216229.html 一. 背景 我们在日常开发中,可能你会遇到这样的需求:"每个月的3号给用户发信息,提 ...

  7. 十六、.net core(.NET 6)搭建基于Redis的Hangfire定时器

    搭建基于Redis的Hangfire定时器 Hangfire的定时配置信息会自动生成在指定到数据库内,包括关系型数据库或非关系型数据库内.目前为止,它在Redis.Oracle上面,可以支持最短15秒 ...

  8. 如何在ASP.NET 5上搭建基于TypeScript的Angular2项目

    一.前言 就在上月,公司的一个同事建议当前的前端全面改用AngularJs进行开发,而我们采用的就是ASP.NET 5项目,原本我的计划是采用TypeScript直接进行Angular2开发.所以借用 ...

  9. 基于 Quartz 开发企业级任务调度应用

    原文地址:http://www.ibm.com/developerworks/cn/opensource/os-cn-quartz/index.html Quartz 基本概念及原理 Quartz S ...

随机推荐

  1. Cannot load driver class: com.mysql.jdbc.Driver

    mysql-connector-java提供了mysql驱动等类库,此处必须引入此依赖,否则将会提示: Cannot load driver class: com.mysql.jdbc.Driver等 ...

  2. java数组 简单了解

    一.关于集合 1.数组,链表和哈希表(散列表)的存储方式 (1)传统的数组结构存储数据会在内存中开辟连续得空间,结合下标从而使得可以快速访问数据,但是删除和添加数据就很浪费资源 (2)链表不需要开辟连 ...

  3. 如何用Vim搭建IDE?

    推荐:http://harttle.com/2015/07/18/vim-cpp.html 转自:http://harttle.com/2015/11/04/vim-ide.html 一年前我从Vim ...

  4. SE_WorkX_提问回顾与个人总结

    项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 要求:正所谓"实践是认识的来源.目的.动力以及检验认识真理性的唯一标准",在经历了一个学期的学习和实践后,请大家写一 ...

  5. CRM的未来发展前景有哪些?

    随着时代的发展,近年来越来越多的国内中小企业开始采用CRM客户关系管理系统,CRM从此不再是大企业的专利,也开始让中小企业得以不断成长.国内CRM行业的发展越来越快, 它的前景是什么?今天小Z就来给大 ...

  6. Java Arrays.sort()重写comparator方法

    先看一下接口 Arrays.sort(T[],Comparator<? super T> c); comparator要重写compare方法 compare方法大概长这样,返回值> ...

  7. 封装axios在util中

    创建util工具类,封装通用的get和post请求 封装axios成工具类,方便大家请求调用 1.创建util文件夹 2.创建request.js 3.封装 //封装请求相关方法 //初始化一个axi ...

  8. [bug] docker: Error response from daemon: Conflict. The container name "/xx" is already in use

    改名.删除或重启容器 参考 https://www.cnblogs.com/youxin/p/12993816.html

  9. [bug] Springboot JPA使用Sort排序时的问题

    参考 https://blog.csdn.net/qq_44039966/article/details/102713779

  10. 【BIGDATA】Grafana告警之webhook的坑

    近日搭建一套基于ELK&Grafana的监控告警平台,目的是将生产端某性能日志导入ES中,通过Grafana进行可视化监测,同时设置告警. 告警内容推送到自建的webhook服务后,转发到指定 ...