最近公司要求将之前的系统设计文档补上,于是大家就都被分配了不同的任务,紧锣密鼓的写起了文档来。发现之前项目中使用了Quartz.Net来做一些定时任务的调度,比如定时的删除未支付的订单,定时检查支付状态是否回调成功等业务。现在看起来对代码居然有点陌生了,于是决定写篇博文来记录下Quartz.Net 的基本使用。

  这里以Quartz.Net 3.0+为例,Quartz.Net中最核心三大对象分别为:

  1. IScheduler: 单元/实例,通过这里完成定时任务的配置,只有单元启动后里面的作业才能正常运行
  2. IJob:定时执行的作业就是Job
  3. ITrigger:定时策略

  我们先来看一下最简单的使用吧,以下代码创建一个Scheduler并启动之。

  1. StdSchedulerFactory factory = new StdSchedulerFactory();
  2. IScheduler scheduler = await factory.GetScheduler();
  3. await scheduler.Start();

  然后我们创建一个继承自IJob的TestJob类,其主要实现IJob的Execute方法,该方法则为当该任务被调度执行的时候所执行的方法。

  1. public class TestJob : IJob
  2. {
  3. public TestJob()
  4. {
  5. Console.WriteLine("This is TestJob的构造函数。。。");
  6. }
  7.  
  8. public async Task Execute(IJobExecutionContext context)
  9. {
  10. await Task.Run(() =>
  11. {
  12. Console.WriteLine($"This is {Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
  13. });
  14. }
  15. }

  接下来使用JobBuilder创建我们的TestJob

  1. IJobDetail jobDetail = JobBuilder.Create<TestJob>()
  2. .WithIdentity("testjob", "group")
  3. .WithDescription("This is TestJob")
  4. .Build();

   创建完Job后需要添加一个trigger,其中StartAt可以指定在隔多少时间后开始触发作业,StartNow则是马上开始,WithCronSchedule是使用Cron表达式来标识时间,关于Cron表达式可以参考另一篇博文

  1. ITrigger trigger = TriggerBuilder.Create()
  2. .WithIdentity("testtrigger1", "group")
  3. .StartAt(new DateTimeOffset(DateTime.Now.AddSeconds()))
  4. //.StartNow()//StartAt
  5. .WithCronSchedule("0/10 * * * * ?")//每隔10秒钟
  6. .WithDescription("This is testjob's Trigger")
  7. .Build();

  创建完Job和trigger后,最后需要将其添加到Scheduler中

  1. await scheduler.ScheduleJob(jobDetail, trigger);

  这样最简单的作业调度就完成了。但是在实际工作中,有时候我们需要传递参数到Job中,这该怎么做呢?Quartz.Net为我们提供了两种方法:

  1. 通过在创建Job的时候在其JobDataMap中添加参数,然后在Job的Execute方法中通过context.JobDetail.JobDataMap来获取
  1. jobDetail.JobDataMap.Add("param", "value1");
  1. JobDataMap dataMap = context.JobDetail.JobDataMap;
  2. dataMap.Get("param")

   2. 通过在trigger中通过trigger.JobDataMap.Add添加参数,在Job中通过context.Trigger.JobDataMap获取

  1. trigger.JobDataMap.Add("param", "value2");
  1. JobDataMap dataMap = context.Trigger.JobDataMap;
  2. dataMap.Get("param")

  3. 在Job中获取参数还可以通过context.MergedJobDataMap来获取参数,但是如果同时通过JobDetail和trigger传递同一个参数,则只能获取到最后添加的那个参数,前面添加的参数会被丢弃,例如上面都添加了param参数,则下面代码获取到的值为value2

  1. JobDataMap dataMap = context.MergedJobDataMap;
  2. Console.WriteLine(dataMap.Get("param"));

  到这里,我们知道了通过Cron表达式的Trigger,虽然Cron可以很灵活的定制时间规则,但是Quartz.Net也提供了另一个常用的Trigger,那就是SimpleTrigger,它的使用方法如下,其表示每隔10秒钟执行一次,最多执行10次

  1. ITrigger trigger = TriggerBuilder.Create()
  2. .WithIdentity("trigger1", "group1")
  3. .StartNow()
  4. .WithSimpleSchedule(x => x
  5. .WithIntervalInSeconds()
  6. .WithRepeatCount()
  7. //.RepeatForever())
  8. .WithDescription("This is testjob's Trigger")
  9. .Build();

  我们知道,在Quartz.Net 3.0之前的版本有一个IStatefulJob接口,表示有状态的作业,意思是上一次的执行结果可以影响到下一次,而在3.0之后的版本,通过特性 PersistJobDataAfterExecution 来实现,下面代码中的DisallowConcurrentExecution 特性表示拒绝同一时间重复执行,即同一任务只能是串行的执行,避免的并发带来的问题。

  1. [PersistJobDataAfterExecution]//执行后保留数据,更新JobDataMap
    [DisallowConcurrentExecution]//拒绝同一时间重复执行,同一任务串行
  2. public class TestStatefulJob : IJob
  3. {
  4.  
  5. }

  Quartz.Net 提供了三个Listerner,即ISchedulerListener,IJobListener,ITriggerListener来分别各个环节的事件,我们可以分别来定义它们的三个实现类

  1. public class CustomSchedulerListener : ISchedulerListener
  2. {
  3. public async Task JobAdded(IJobDetail jobDetail, CancellationToken cancellationToken = default(CancellationToken))
  4. {
  5. await Task.Run(() =>
  6. {
  7. Console.WriteLine($"This is {nameof(CustomSchedulerListener)} JobAdded {jobDetail.Description}");
  8. });
  9. }
  10.  
  11. public Task JobDeleted(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken))
  12. {
  13. throw new NotImplementedException();
  14. }
  15.  
  16. public Task JobInterrupted(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken))
  17. {
  18. throw new NotImplementedException();
  19. }
  20.  
  21. public Task JobPaused(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken))
  22. {
  23. throw new NotImplementedException();
  24. }
  25.  
  26. public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken))
  27. {
  28. throw new NotImplementedException();
  29. }
  30.  
  31. public Task JobScheduled(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
  32. {
  33. throw new NotImplementedException();
  34. }
  35.  
  36. public Task JobsPaused(string jobGroup, CancellationToken cancellationToken = default(CancellationToken))
  37. {
  38. throw new NotImplementedException();
  39. }
  40.  
  41. public Task JobsResumed(string jobGroup, CancellationToken cancellationToken = default(CancellationToken))
  42. {
  43. throw new NotImplementedException();
  44. }
  45.  
  46. public Task JobUnscheduled(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken))
  47. {
  48. throw new NotImplementedException();
  49. }
  50.  
  51. public Task SchedulerError(string msg, SchedulerException cause, CancellationToken cancellationToken = default(CancellationToken))
  52. {
  53. throw new NotImplementedException();
  54. }
  55.  
  56. public Task SchedulerInStandbyMode(CancellationToken cancellationToken = default(CancellationToken))
  57. {
  58. throw new NotImplementedException();
  59. }
  60.  
  61. public Task SchedulerShutdown(CancellationToken cancellationToken = default(CancellationToken))
  62. {
  63. throw new NotImplementedException();
  64. }
  65.  
  66. public Task SchedulerShuttingdown(CancellationToken cancellationToken = default(CancellationToken))
  67. {
  68. throw new NotImplementedException();
  69. }
  70.  
  71. public async Task SchedulerStarted(CancellationToken cancellationToken = default(CancellationToken))
  72. {
  73. await Task.Run(() =>
  74. {
  75. Console.WriteLine($"This is {nameof(CustomSchedulerListener)} SchedulerStarted ");
  76. });
  77. }
  78.  
  79. public async Task SchedulerStarting(CancellationToken cancellationToken = default(CancellationToken))
  80. {
  81. await Task.Run(() =>
  82. {
  83. Console.WriteLine($"This is {nameof(CustomSchedulerListener)} SchedulerStarting ");
  84. });
  85. }
  86.  
  87. public Task SchedulingDataCleared(CancellationToken cancellationToken = default(CancellationToken))
  88. {
  89. throw new NotImplementedException();
  90. }
  91.  
  92. public Task TriggerFinalized(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
  93. {
  94. throw new NotImplementedException();
  95. }
  96.  
  97. public Task TriggerPaused(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken))
  98. {
  99. throw new NotImplementedException();
  100. }
  101.  
  102. public Task TriggerResumed(TriggerKey triggerKey, CancellationToken cancellationToken = default(CancellationToken))
  103. {
  104. throw new NotImplementedException();
  105. }
  106.  
  107. public Task TriggersPaused(string triggerGroup, CancellationToken cancellationToken = default(CancellationToken))
  108. {
  109. throw new NotImplementedException();
  110. }
  111.  
  112. public Task TriggersResumed(string triggerGroup, CancellationToken cancellationToken = default(CancellationToken))
  113. {
  114. throw new NotImplementedException();
  115. }
  116. }
  1. public class CustomJobListener : IJobListener
  2. {
  3. public string Name => "CustomJobListener";
  4.  
  5. public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
  6. {
  7. await Task.Run(()=> {
  8. Console.WriteLine($"CustomJobListener JobExecutionVetoed {context.JobDetail.Description}");
  9. });
  10. }
  11.  
  12. public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
  13. {
  14. await Task.Run(() => {
  15. Console.WriteLine($"CustomJobListener JobToBeExecuted {context.JobDetail.Description}");
  16. });
  17. }
  18.  
  19. public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken))
  20. {
  21. await Task.Run(() => {
  22. Console.WriteLine($"CustomJobListener JobWasExecuted {context.JobDetail.Description}");
  23. });
  24. }
  25. }
  1. public class CustomTriggerListener : ITriggerListener
  2. {
  3. public string Name => "CustomTriggerListener";
  4.  
  5. public async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default(CancellationToken))
  6. {
  7. await Task.Run(() =>
  8. {
  9. Console.WriteLine($"CustomTriggerListener TriggerComplete {trigger.Description}");
  10. });
  11. }
  12.  
  13. public async Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
  14. {
  15. await Task.Run(() =>
  16. {
  17. Console.WriteLine($"CustomTriggerListener TriggerFired {trigger.Description}");
  18. });
  19. }
  20.  
  21. public async Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
  22. {
  23. await Task.Run(() =>
  24. {
  25. Console.WriteLine($"CustomTriggerListener TriggerMisfired {trigger.Description}");
  26. });
  27. }
  28.  
  29. /// <summary>
  30. /// 要不要放弃job
  31. /// </summary>
  32. /// <param name="trigger"></param>
  33. /// <param name="context"></param>
  34. /// <param name="cancellationToken"></param>
  35. /// <returns></returns>
  36. public async Task<bool> VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
  37. {
  38. await Task.Run(() =>
  39. {
  40. Console.WriteLine($"CustomTriggerListener TriggerMisfired {trigger.Description}");
  41. });
  42. return false;//false才能继续执行
  43. }
  44. }

  之后我们需要在创建Scheduler的时候将其添加到scheduler中

  1. StdSchedulerFactory factory = new StdSchedulerFactory();
  2. IScheduler scheduler = await factory.GetScheduler();
  3. scheduler.ListenerManager.AddSchedulerListener(new CustomSchedulerListener());
  4. scheduler.ListenerManager.AddTriggerListener(new CustomTriggerListener());
  5. scheduler.ListenerManager.AddJobListener(new CustomJobListener());
  6. await scheduler.Start();

  至此,我们的demo中都是使用console来自定义的记录操作过程,但是Quartz.Net也提供了一个日志组件 ILogProvider,我们创建一个CustomConsoleLogProvider,其实现了ILogProvider

  1. public class CustomConsoleLogProvider : ILogProvider
  2. {
  3. public Logger GetLogger(string name)
  4. {
  5. return (level, func, exception, parameters) =>
  6. {
  7. if (level >= LogLevel.Info && func != null)
  8. {
  9. Console.WriteLine($"[{ DateTime.Now.ToLongTimeString()}] [{ level}] { func()} {string.Join(";", parameters.Select(p => p == null ? " " : p.ToString()))} 自定义日志{name}");
  10. }
  11. return true;
  12. };
  13. }
  14. public IDisposable OpenNestedContext(string message)
  15. {
  16. throw new NotImplementedException();
  17. }
  18.  
  19. public IDisposable OpenMappedContext(string key, string value)
  20. {
  21. throw new NotImplementedException();
  22. }
  23. }

  然后通过Quartz.Logging.LogProvider来添加自定义的LogProvider,其在运行中会通过GetLogger来记录日志。

  1. LogProvider.SetCurrentLogProvider(new CustomConsoleLogProvider());

  到这里关于Quartz.Net的基本使用就介绍到这里,其进阶待下一篇再继续。

任务调度之Quartz.Net基础的更多相关文章

  1. 免费开源的DotNet任务调度组件Quartz.NET(.NET组件介绍之五)

    很多的软件项目中都会使用到定时任务.定时轮询数据库同步,定时邮件通知等功能..NET Framework具有“内置”定时器功能,通过System.Timers.Timer类.在使用Timer类需要面对 ...

  2. 任务调度框架Quartz原理简介

    [TOC] 第一章 Quartz 1.1 Quartz概念 Quartz是OpenSymphony开源组织的一个Java开源项目, 在2009被Terracotta收购.Quartz官网 1.2 Qu ...

  3. Java任务调度框架Quartz入门

    Quartz[kwɔːts]:石英,其框架和名字一样简单朴素又不失魅力,在Java程序界,Quartz大名鼎鼎,很多Java应用几乎都集成或构建了一个定时任务调度系统,Quartz是一个定时任务调度框 ...

  4. [源码分析] 定时任务调度框架 Quartz 之 故障切换

    [源码分析] 定时任务调度框架 Quartz 之 故障切换 目录 [源码分析] 定时任务调度框架 Quartz 之 故障切换 0x00 摘要 0x01 基础概念 1.1 分布式 1.1.1 功能方面 ...

  5. 任务调度TimerTask&Quartz的 Java 实现方法与比较

    文章引自--https://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/ 前言 任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自 ...

  6. 企业级任务调度框架Quartz(1) --企业应用中的任务调度介绍

    由于目前的工作内容为建行CLPM批处理业务的设计工作,所以很好的理解批处理所用的任务调度框架Quartz势在必行:为了能够更好的去服务于工作,也 为了提升自己,所以我学习了Quartz Job Sch ...

  7. 通过源码分析Java开源任务调度框架Quartz的主要流程

    通过源码分析Java开源任务调度框架Quartz的主要流程 从使用效果.调用链路跟踪.E-R图.循环调度逻辑几个方面分析Quartz. github项目地址: https://github.com/t ...

  8. SpringBoot整合任务调度框架Quartz及持久化配置

    目录 本篇要点 SpringBoot与Quartz单机版快速整合 引入依赖 创建Job 调度器Scheduler绑定 自动配置,这里演示SimpleScheduleBuilder 手动配置,这里演示C ...

  9. Spring任务调度之Quartz集成

    推荐一个博客:http://blog.csdn.net/column/details/14251.html 基本概念 Job:是一个接口,只有一个方法void execute(JobExecution ...

随机推荐

  1. 11、spark内核架构剖析与宽窄依赖

    一.内核剖析 1.内核模块 1.Application 2.spark-submit 3.Driver 4.SparkContext 5.Master 6.Worker 7.Executor 8.Jo ...

  2. [php][thinkphp] 记一次Composer Linux版安装以及用它进行thinkphp项目初始化

    Composer安装thinkphp,thinkphp5.1开始官网不在提供下载包,只能通过git clone 和Composer包管理器进行下载. php中开启exec,system等函数调用系统命 ...

  3. mybatis-sqlite日期类型对应关系

    1.问题 sqlite数据库 user表,create_time字段,类型DATETIME,设置默认值datetime('now') mybatis,User实体,createTime类型为java. ...

  4. ubuntu之路——day9.1 深度学习超参数的调优

    参数重要性: 第一阶:α即learning rate 第二阶:momentum中的β,hidden units的数量,mini-batch的大小 第三阶:hidden layers的数量,learni ...

  5. nodejs搜索包的流程

    执行npm install后,如果打包成功,会在当前目录下生成一个node_modules的文件夹,里面存放着我们所需的依赖包. 当需要引用时,例如: var math = require(" ...

  6. elementUI 列表里面含有多选框,当翻页的时候依然保持之前页多选不变

    el-table的type="selection"的使用 场景:el-table,type="selection"时,重新请求后,设置列表更新前的已勾选项 踩坑 ...

  7. percona mysql5.7进程出现大量unauthenticated user解决记录

    现象:http://task.chinasoft.com.wx/ 所有任务能打开,我的任务打开很慢 有些人能用,有些人不能用,数据库出现大量的未认证用户连接,连接数利用率超过70% 重启nginx,a ...

  8. 泡泡一分钟:Project AutoVision - Localization and 3D Scene Perception for an Autonomous Vehicle with a Multi-Camera System

    Project AutoVision - Localization and 3D Scene Perception for an Autonomous Vehicle with a Multi-Cam ...

  9. 泡泡一分钟:Semi-Dense Visual-Inertial Odometry and Mapping for Quadrotors with SWAP Constraints

    张宁 Semi-Dense Visual-Inertial Odometry and Mapping for Quadrotors with SWAP Constraints 具有SWAP约束的四旋翼 ...

  10. 基于Source Insight_Scan的C/C++静态代码检查工具安装说明

    基于Source Insight_Scan的C/C++静态代码检查工具安装说明   本文链接:https://blog.csdn.net/M19930517/article/details/79977 ...