Quartz.Net源码Example之Quartz.Examples
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) 的日期和时间,
不建议使用DateTime,因为DateTime一般默认为本地时间+时区,不会有时间偏移的概念,不同时区的时间相等但是不是同一时间。
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}");
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))
注意: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说明
01_SimpleJobScheduler
最简单的调度程序,任务是打印当前时间
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(); 获取调度任务数据
03_SchedulingCapabilitiesUsingCronTriggers
cron的触发器实例
具体cron触发可通过查看cron在线生成来确定触发周期
04_JobParametersAndJobsStateMaintenance
JobDataMap添加数据,IJob实例中获取并修改的实例
05_SchedulingJobsSettingMisfireInstructions
JobDataMap实例(同上)和 一个单元测试
- UsingJobData(StatefulDumbJob.ExecutionDelay, 10000L) 在IJobDetail实例时调用该方法赋值
- WithMisfireHandlingInstructionNowWithExistingCount() 设置了运行失败后的计数---通过await Task.Delay(10000L)实现的
06_JobExecutionExceptions
JobExecutionException的例子
- 作业重新开始执行
// 将Exception异常转换为JobExecutionException异常
JobExecutionException e2 = new JobExecutionException(e);
// 如果报错不可以修复,可以让该触发器结束执行,避免一直报错
e2.UnscheduleAllTriggers = true;
// 如果报错可以修复,可以在报错修复后重新执行
e2.RefireImmediately = true;
throw e2;
07_InterrupInProgressJobs
调度程序中每七秒中断一次作业,共中断50次
// 调度程序中中断作业,job.Key 作业的唯一key
await sched.Interrupt(job.Key);
// IJob实例中判断中断代码片段
// 当该值为true时,要求中断
context.CancellationToken.IsCancellationRequested
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")
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_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_RunningLargeNumberOfJobs
500个任务间隔100ms秒执行,可以查看任务执行效率和资源信息
12_RemoteClientServerJobScheduling
代码被注释,官网不建议使用
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_RunJobsByPriorityWithTriggersPriority
触发器优先级的例子,默认是5,在相同时间运行时不同级别同时运行时,级别越高越先执行
ITrigger实例.WithPriority(10)
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_RunningAsynchronousJobs
由于作业没执行完毕触发器会再次运行作业,因此相同的作业会异步执行
Quartz.Net源码Example之Quartz.Examples的更多相关文章
- Pytorch学习之源码理解:pytorch/examples/mnists
Pytorch学习之源码理解:pytorch/examples/mnists from __future__ import print_function import argparse import ...
- cache2go源码最后一讲 - examples
先看一下我们讲到哪里了: cache2go的源码前面我们已经讲完了cacheitem和cachetable的实现,今天cahce和examples会一起讲完~ 1.cache.go源码 ...
- java ssm 后台框架平台 项目源码 websocket IM quartz springmvc
A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器freemaker模版技术 ,0个 ...
- quartz(7)-源码分析
定时器启动 上图通过spring加载quartz <bean id="scheduler" class="org.springframework.schedulin ...
- Quartz.Net系列(三):解读Quartz.Net源码领略设计模式在其中的应用
1.Builder(建造者)模式 JobBuilder DateBuilder 其他的Builder(TriggerBuilder.SchedulerBuilder等) 2.抽象工厂模式 ISch ...
- quartz集群调度机制调研及源码分析---转载
quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...
- 定时组件quartz系列<三>quartz调度机制调研及源码分析
quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...
- anki_vector SDK源码解析(教程)
一:最近anki vector robot开放了Python SDK,我听到的第一时间就赶快上网查了查,先抛几个官网重要链接吧: Python编程API手册及环境搭建等: https://sdk-re ...
- quartz.net任务调度:源码及使用文档
目录: 1.quartz.net任务调度:源码及使用文档 2.quartz.net插件类库封装 前言 前段时间把自己封装quartz.net 类库的过程总结到博客园,有网友想要看一下源码,所以就把源码 ...
- quartz.net插件类库封装(含源码)
1.前言 目录: 1.quartz.net任务调度:源码及使用文档 2.quartz.net插件类库封装 最近项目需要做一写任务作业调度的工作,最终选择了quartz.net这个插件,它提供了巨大的灵 ...
随机推荐
- vs自定义工程宏
[视图] ---->[其他窗口]----> [属性管理器 ]右键工程---->[添加新项目属性表]打开配置debug/release打开propertysheet找到用户宏即可添加
- 如何在Spring Boot开启事务
说到事务,那什么是事务呢? 事务(Transaction),一般是指要做的或所做的事情. 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行. ...
- 我的Spark学习笔记
一.架构设计 Driver根据用户代码构建计算流图,拆解出分布式任务并分发到 Executors 中去:每个Executors收到任务,然后处理这个 RDD 的一个数据分片子集 DAGSchedule ...
- [leetcode] 713. Subarray Product Less Than K
题目 Given an array of integers nums and an integer k, return the number of contiguous subarrays where ...
- C#多线程之高级篇(上)
前言 抛开死锁不谈,只聊性能问题,尽管锁总能粗暴的满足同步需求,但一旦存在竞争关系,意味着一定会有线程被阻塞,竞争越激烈,被阻塞的线程越多,上下文切换次数越多,调度成本越大,显然在高并发的场景下会损害 ...
- 推荐一款 .NET 编写的 嵌入式平台的开源仿真器--Renode
Renode 是一个开发框架,通过让你模拟物理硬件系统来加速物联网和嵌入式系统开发. Renode 可以模拟 Cortex-M.RISC-V 等微控制器,不仅可以模拟 CPU指令,还可以模拟外设,甚至 ...
- esp-01和esp-01s烧录固件和程序
准备工具 USB-TTL 杜邦线若干 esp-01s烧录固件 我烧录的固件是 micropython, 使用的软件是 uPyCraft esp-01s烧录固件接线方法: esp-01s usb-ttl ...
- 基于.net C# Socket WinForm MQTT 客户端开发
1.什么是MQTT? MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的&quo ...
- MySQL数据库下载以及启动软件的详细步骤
第一步>>>在浏览器上百度上搜索MySQL 如何判断官网?有官网两个字的或者纯英文解释的大概率就是官网 第二步>>>点击DOWNLOAWDS 第三步>> ...
- js-day04-作业
// -------------------------Day04homework 大练习------------------------ #### 练习题1: * 显示用户输入内容 * 要求: 1. ...