搭建基于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的全部内容,仅用于入门参考。对于其他定时用法、以及各种比较飘的使用,各位大佬可以自行变种。如果有什么建议或意见,也欢迎留言~~

最新文章

  1. 初学jquery,自己写的一个jquery幻灯片,代码有些笨拙,希望有大神可以指点一二,精简一下代码
  2. power
  3. Potocol Buffer详解
  4. Canvas 教程
  5. hdu 2082
  6. auto_ptr,shared_ptr 智能指针的使用
  7. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(14)-系统小结
  8. spring注解机制和XML配置机制之间的比较
  9. PHP学习日记(一)——类、函数的使用
  10. RedHat7上安装MySQL5.7.16
  11. Xcode9的xib只支持iOS7.0及以上版本
  12. php+ajax文件上传
  13. vue+富文本编辑器UEditor
  14. Kong(V1.0.2) Clustering Reference
  15. Okhttp3请求网络开启Gzip压缩
  16. object detection[faster rcnn]
  17. oracle数据库连接 ORA-12638:身份证明检索失败
  18. yum 安装 jenkins
  19. python sqlite3 数据库操作
  20. mint 安装过程

热门文章

  1. JavaWeb——MySQL基础
  2. blazor发布之后 刷新404的解决方法
  3. IOC随笔小记录
  4. Davinci 可视化系统部署安装及简单使用
  5. 前端的MySQL基础
  6. [设计模式] 设计模式课程(十六)-- 备忘录模式(Memento)
  7. 【BIGDATA】在Centos上部署ElasticSearch 7.3.2及kibana
  8. 本文介绍使用windows系统自带的远程桌面mstsc连接Centos 7.x远程桌面的基本方法。
  9. SSH连接自动断开的解决方法(deb/rpm)
  10. 使用shell+python脚本实现系统监控并发送邮件