Quartz.Examples

反射-Example批量执行

​ 实现思路:定义一个统一的接口,需要实现的类全部实现该接口;通过反射获取实现该接口的实例并触发其中的方法。

  • 定义统一的接口

    // 所有要实现类都要有Run方法
    public interface IExample
    {
    Task Run();
    }
  • 利用反射实例化

    //反射的方式获得程序配置信息
    Assembly asm = typeof(Program).GetTypeInfo().Assembly;
    // 获得该程序的所有类型
    Type[] types = asm.GetTypes();
    List<Type> typeList = new List<Type>();
    foreach (Type t in types)
    {
    // 判断是否继承的IExample接口
    if (new List<Type>(t.GetInterfaces()).Contains(typeof(IExample)))
    {
    typeList.Add(t);
    }
    }
    // 实例化第一个接口实现类
    IExample example = ObjectUtils.InstantiateType<IExample>(typeList[0]);
    // 执行接口中的Run方法
    await example.Run().ConfigureAwait(false);
DateTimeOffset

​ UTC时间为协调世界时 (UTC) 的日期和时间,

  1. 不建议使用DateTime,因为DateTime一般默认为本地时间+时区,不会有时间偏移的概念,不同时区的时间相等但是不是同一时间。

  2. DateTimeOffset.Now和DateTimeOffset.UtcNow

    • 相同点 获得的实际值一样(ToUnixTimeSecondes)

      // Now秒:   1675238417
      // UtcNow秒:1675238417
      Console.WriteLine($"Now秒: {DateTimeOffset.Now.ToUnixTimeSeconds()}");
      Console.WriteLine($"UtcNow秒:{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}");
    • 不同点 展示不一样,Now为本地时区时间,UtcNow为0时区的时间。

      // Now时间   :2023/2/1 16:00:17 +08:00
      // UtcNow时间:2023/2/1 8:00:17 +00:00
      Console.WriteLine($"Now时间 :{DateTimeOffset.Now}");
      Console.WriteLine($"UtcNow时间:{DateTimeOffset.UtcNow}");
  3. DateTime与DateTimeOffset 转换

    //DateTimeOffset 转 DateTime
    // 时区丢失,即dateTime.Kind为UnSpecified
    DateTime dateTime=dateTimeOffset.DateTime;
    // 时区为Local
    DateTime dateTime=DateTime.SpecifyKind(dateTimeOffset,DateTimeKind.Local);
    // 本地时区换算为本地时间,且dateTime.Kind为Local
    DateTime dateTime=dateTimeOffset.LocalTime;
    // 本地时区换算为utc时间(0时区),且dateTime.Kind为Utc
    DateTime dateTime=dateTimeOffset.UtcDateTime;
    // DateTime转DateTimeOffset
    // 直接转换为本地时间+时区
    DateTimeOffset dateTimeOffset = new DateTimeOffset(dateTime);
    // Utc时间 dateTimeOffset与dateTime时区会不同,造成展示的时间不同
    DateTimeOffset dateTimeOffset = new DateTimeOffset(dateTime, TimeZoneInfo.Local.GetUtcOffset(dateTime));
    // 设置时间+查找时区相对应的时间 dateTimeOffset与dateTime会相同
    DateTimeOffset dateTimeOffset = new DateTimeOffset(dateTime, TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time").GetUtcOffset(dateTime))
  4. 注意:Quartz.NET使用了DateTimeOffset进行的时间操作

TimeSpan

时间间隔,例如

TimeSpan.FromSeconds(65) 返回65秒的TimeSpan实例

TimeSpan.Zero 间隔是0秒

new TimeSpan(2, 14, 18) 间隔2小时14分钟18秒

DateTime减法

DateTime departure = new DateTime(2010, 6, 12, 18, 32, 0);
DateTime arrival = new DateTime(2010, 6, 13, 22, 47, 0);
TimeSpan travelTime = arrival - departure;
// 结果:6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00
DateBuilder

Quzrtz.NET自带设置类,方便设置和操作DateTimeOffset类。

// date时间后的一个小时,例如date为8:44:59,调用方法后获得时间为 9:00:00
// 如果参数为null,则为当前时间
static DateTimeOffset EvenHourDate(DateTimeOffset? date)
// 同DateBuilder.EvenHourDate(null);
static DateTimeOffset EvenHourDateAfterNow()
// data时间前的一个小时,例如date为8:44:59,调用方法后获得时间为 8:00:00
static DateTimeOffset EvenHourDateBefore(DateTimeOffset? date)
// 同EvenHourDate,不过由小时变为了分钟; EvenMinuteDateBefore和EvenMinuteDateAfterNow同上
static DateTimeOffset EvenMinuteDate(DateTimeOffset? date)
// EvenSecondDate EvenSecondDateBefore EvenSecondDateAfterNow同上 /*
当前时间以IntervalUnit为单位增加interval的时间
IntervalUnit为枚举类
Millisecond, 毫秒
Second, 秒
Minute, 分
Hour, 小时
Day, 天
Week, 周
Month, 月
Year 年
例如:DateBuilder.FutureDate(1, IntervalUnit.Hour); 当前时间增加一小时后的DateTimeOffset实例
*/
static DateTimeOffset FutureDate(int interval, IntervalUnit unit)
// 创建一个当前时间的DateBuilder实例,可通过Build()方法获得DateTimeOffset
static DateBuilder NewDate
/*
TimeZoneInfo 时区,根据时区不同获取不同时区的当前时间
*/
static DateBuilder NewDateInTimeZone(TimeZoneInfo tz)
// 获得下一分/秒的时间
static DateTimeOffset NextGivenMinuteDate(DateTimeOffset? date, int minuteBase)
static DateTimeOffset NextGivenSecondDate(DateTimeOffset? date, int secondBase)
// 当前时间加上hour小时,minute分钟,second秒
static DateTimeOffset TodayAt(int hour, int minute, int second)
// 当前时间加上1天,hour小时,minute分钟,second秒
static DateTimeOffset TomorrowAt(int hour, int minute, int second)
各Demo说明
  1. 01_SimpleJobScheduler

    最简单的调度程序,任务是打印当前时间

  2. 02_SchedulingCapabilitiesUsingSimpleTriggers

    简单的触发器实例-重复执行,定时执行等

    • TriggerBuilder.Create()创建ISimpleTrigger的实例
    • .WithSimpleSchedule(x => x.WithIntervalInSeconds(10).WithRepeatCount(10)) 每隔10s循环10次,共11次
    • sched.RescheduleJob(trigger.Key, trigger) 重启触发器trigger为触发器实例
    • SchedulerMetaData metaData = await sched.GetMetaData(); 获取调度任务数据
  3. 03_SchedulingCapabilitiesUsingCronTriggers

    cron的触发器实例

    具体cron触发可通过查看cron在线生成来确定触发周期

  4. 04_JobParametersAndJobsStateMaintenance

    JobDataMap添加数据,IJob实例中获取并修改的实例

  5. 05_SchedulingJobsSettingMisfireInstructions

    JobDataMap实例(同上)和 一个单元测试

    • UsingJobData(StatefulDumbJob.ExecutionDelay, 10000L) 在IJobDetail实例时调用该方法赋值
    • WithMisfireHandlingInstructionNowWithExistingCount() 设置了运行失败后的计数---通过await Task.Delay(10000L)实现的
  6. 06_JobExecutionExceptions

    JobExecutionException的例子

    • 作业重新开始执行
    // 将Exception异常转换为JobExecutionException异常
    JobExecutionException e2 = new JobExecutionException(e);
    // 如果报错不可以修复,可以让该触发器结束执行,避免一直报错
    e2.UnscheduleAllTriggers = true;
    // 如果报错可以修复,可以在报错修复后重新执行
    e2.RefireImmediately = true;
    throw e2;
  7. 07_InterrupInProgressJobs

    调度程序中每七秒中断一次作业,共中断50次

    // 调度程序中中断作业,job.Key 作业的唯一key
    await sched.Interrupt(job.Key);
    // IJob实例中判断中断代码片段
    // 当该值为true时,要求中断
    context.CancellationToken.IsCancellationRequested
  8. 08_ExcludeTimePeriodsUsingCalendars

    通过判断ModifiedByCalendar,来排除不执行的时间

    // 创建日历
    AnnualCalendar holidays = new AnnualCalendar();
    // 生成一个排除的时间
    DateTime fourthOfJuly = new DateTime(DateTime.UtcNow.Year, 7, 4);
    // 在日历中添加该时间
    holidays.SetDayExcluded(fourthOfJuly, true);
    // 将日历添加到调度程序中,,第一个参数为实例名称,第三个参数为替换之前的日历,第四个参数为更新触发器
    await sched.AddCalendar("holidays", holidays, false, false);
    // 引用实例名称
    ISimpleTrigger的实例.ModifiedByCalendar("holidays")
  9. 09_TriggeringAJobUsingJobListeners

    在作业中启用了监听,并在监听中创建了新的作业

    • 创建监听并添加到调度程序中

      // 实例化监听
      IJobListener listener = new SimpleJob1Listener();
      // 创建匹配器,并设置作业的key
      IMatcher<JobKey> matcher = KeyMatcher<JobKey>.KeyEquals(job.Key);
      // 将监听和匹配器关联
      sched.ListenerManager.AddJobListener(listener, matcher);
    • SimpleJob1Listener

      public class SimpleJob1Listener : IJobListener
      {
      public virtual string Name => "job1_to_job2";
      // 作业将被执行
      public virtual Task JobToBeExecuted(IJobExecutionContext inContext, CancellationToken canncellationToken)
      {
      return Task.CompletedTask;
      }
      // 作业完成执行
      public virtual Task JobExecutionVetoed(IJobExecutionContext inContext,CancellationToken canncellationToken)
      {
      return Task.CompletedTask;
      }
      // 作业执行完成
      public virtual async Task JobWasExecuted(IJobExecutionContext inContext,JobExecutionException? inException,CancellationToken canncellationToken = default)
      {
      //在监听器中创建作业和触发器
      IJobDetail job2 = JobBuilder.Create<SimpleJob2>()
      .WithIdentity("job2")
      .Build(); ITrigger trigger = TriggerBuilder.Create()
      .WithIdentity("job2Trigger")
      .StartNow()
      .Build(); try
      {
      // 将触发器和作业添加到调度程序中
      await inContext.Scheduler.ScheduleJob(job2, trigger, canncellationToken);
      }
      catch (SchedulerException e)
      {
      Console.Error.WriteLine("Unable to schedule job2!");
      Console.Error.WriteLine(e.StackTrace);
      }
      }
      }
  10. 10_RunningJobsByPlugInXmlConfiguration

    通过xml配置任务和触发器,xml参见:quartz_jobs.xml

    • MergedJobDataMap

      if (context.MergedJobDataMap.Count > 0)
      {
      ICollection<string> keys = context.MergedJobDataMap.Keys;
      foreach (string key in keys)
      {
      var val = context.MergedJobDataMap.GetString(key);
      Console.WriteLine(" - jobDataMap entry: {0} = {1}", key, val);
      }
      }
  11. 11_RunningLargeNumberOfJobs

    500个任务间隔100ms秒执行,可以查看任务执行效率和资源信息

  12. 12_RemoteClientServerJobScheduling

    代码被注释,官网不建议使用

  13. 13_ClusteringJobsExecution

    集群作业(感觉就是多个调度服务使用同一个数据库的例子)

    • 使用数据库存储

      IScheduler sched = await SchedulerBuilder.Create()
      .WithId("instance_one")
      .WithName("TestScheduler")
      // 线程池
      .UseDefaultThreadPool(x => x.MaxConcurrency = 5)
      //失效后暂停60s
      .WithMisfireThreshold(TimeSpan.FromSeconds(60))
      .UsePersistentStore(x =>
      {
      x.UseProperties = true;
      x.UseClustering();
      // 连接字符串
      x.UseSqlServer(TestConstants.SqlServerConnectionString);
      x.UseJsonSerializer();
      })
      .BuildScheduler();
  14. 14_RunJobsByPriorityWithTriggersPriority

    触发器优先级的例子,默认是5,在相同时间运行时不同级别同时运行时,级别越高越先执行

    ITrigger实例.WithPriority(10)

  15. 15_ConfigureJobSchedulingByUsingXmlConfigurations

    使用xml进行调度器的配置

    var sched = await SchedulerBuilder.Create()
    .WithName("XmlConfiguredInstance")
    .UseDefaultThreadPool(maxConcurrency: 5)
    // 作业和触发器都通过xml进行配置
    .UseXmlSchedulingConfiguration(x =>
    {
    // xml文件
    x.Files = new[] { "~/quartz_jobs.xml" };
    // FailOnFileNotFound默认为true
    x.FailOnFileNotFound = true;
    // FailOnSchedulingError 默认为false
    x.FailOnSchedulingError = true;
    })
    .BuildScheduler();
  16. 16_RunningAsynchronousJobs

    由于作业没执行完毕触发器会再次运行作业,因此相同的作业会异步执行

Quartz.Net源码Example之Quartz.Examples的更多相关文章

  1. Pytorch学习之源码理解:pytorch/examples/mnists

    Pytorch学习之源码理解:pytorch/examples/mnists from __future__ import print_function import argparse import ...

  2. cache2go源码最后一讲 - examples

    先看一下我们讲到哪里了: cache2go的源码前面我们已经讲完了cacheitem和cachetable的实现,今天cahce和examples会一起讲完~ 1.cache.go源码 ​      ...

  3. java ssm 后台框架平台 项目源码 websocket IM quartz springmvc

    A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器freemaker模版技术 ,0个 ...

  4. quartz(7)-源码分析

    定时器启动 上图通过spring加载quartz <bean id="scheduler" class="org.springframework.schedulin ...

  5. Quartz.Net系列(三):解读Quartz.Net源码领略设计模式在其中的应用

    1.Builder(建造者)模式 JobBuilder  DateBuilder  其他的Builder(TriggerBuilder.SchedulerBuilder等) 2.抽象工厂模式 ISch ...

  6. quartz集群调度机制调研及源码分析---转载

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  7. 定时组件quartz系列<三>quartz调度机制调研及源码分析

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  8. anki_vector SDK源码解析(教程)

    一:最近anki vector robot开放了Python SDK,我听到的第一时间就赶快上网查了查,先抛几个官网重要链接吧: Python编程API手册及环境搭建等: https://sdk-re ...

  9. quartz.net任务调度:源码及使用文档

    目录: 1.quartz.net任务调度:源码及使用文档 2.quartz.net插件类库封装 前言 前段时间把自己封装quartz.net 类库的过程总结到博客园,有网友想要看一下源码,所以就把源码 ...

  10. quartz.net插件类库封装(含源码)

    1.前言 目录: 1.quartz.net任务调度:源码及使用文档 2.quartz.net插件类库封装 最近项目需要做一写任务作业调度的工作,最终选择了quartz.net这个插件,它提供了巨大的灵 ...

随机推荐

  1. Maven 聚合工程的创建

    简单场景举例 聚合工程创建示例 说明: 创建 Maven Project:表示创建 maven 项目,new Project 方式创建 创建 Maven Module:表示创建 maven 项目,ne ...

  2. shardingsphere-jdbc 水平分表学习记录

    放在自己博客里搬过来一份~ 前司使用的是自己魔改的TDDL,在家时间比较多就尝试学一些业内比较常用的中间件. 这里记录一下学习中遇到的一些问题. 环境 设置的比较简单(太懒了就测试了几个表), 两个分 ...

  3. Redis可视化管理工具-RedisDesktopManager

    Windows客户端,访问Redis数据库并执行一些基本操作. 链接:https://pan.baidu.com/s/1OuGqIfbpGwglC-642rECbQ 提取码:m6uo

  4. RabbitMQ GUI客户端工具(RabbitMQ Assistant)

    RabbitMQ GUI客户端工具(RabbitMQ Assistant) 平时用控制台或者网页进行管理不免有点不方便,尤其在读取消息的时候不支持过滤和批量发送消息,在此推荐一个漂亮的GUI客户端工具 ...

  5. 质数之和【计算第x个到第y个质数之和】

    题目:质数之和 已知,第一个质数是2,第二个质数是3,第三个质数是5,第四个质数是7,第五个质数是11,第六个质数是13,第七个质数是17,输入两个不相等的正整数a和b,求出第a个质数到第b个质数当中 ...

  6. 关于python统计一个列表中每个元素出现的频率

    第一种写法: a = ['h','h','e','a','a'] result = {} for i in a: if i not in result: result[i] = 1 else: res ...

  7. JDBC Request 中 Variable names 以及 Result variable name 的使用方法

    1.Variable name 的使用方法 设置好JDBC Connection Configuration.JDBC Request  具体配置百度 如果数据库查询的结果不止一列那就在Variabl ...

  8. JavaScript入门②-函数(1)基础{浅出}

    01.JS函数基础 1.1.函数定义 函数(方法)就是一段定义好的逻辑代码,函数本身也是一个object引用对象.三种函数构造方式: ① 函数申明:function 函数名(参数){代码},申明函数有 ...

  9. 解决aspnetcore-browser-refresh.js:234 WebSocket connection to 'wss://localhost:62356/Admin/' failed问题

    前言 前段时间升级了Visual Studio到v17.1.1最新版本,然后今天来运行之前的一个.net5项目一直提示:aspnetcore-browser-refresh.js:234 WebSoc ...

  10. <五>基于CAS操作的atomic原子类型

    C++11多线程类库中提供了 include包含了很多原子类型 原子操作 若干汇编指令具有读-修改-写类型,也就是说它们访问存储器单元两次,第一次读原值,第二次写新值 假定运行在两个cpu上的两个内核 ...