DotNetCore跨平台~Quartz定时单次任务
之前写过一篇文件《DotNetCore跨平台~Quartz热部署的福音~监控文件夹的变化》,今天主要把框架优化了一下,支持外部触发,并支持外部将参数以JobDataMap形式进行输入,然后在咱们的Job里进行使用它,故称参数化任务。
Quartz使用场景:
- 定时单次任务:在未来某个时间去执行一次
- 定点任务 :在某个时间去执行,可以是轮询的
- 周期任务 :按某个时间间隔去轮询执行
今天说的外部触发的任务是指第一种,即在未来某个时间点去执行,并且只执行一次。说一下思路,这种任务某个JobBase的子类,它需要重写属性IsSingle,将值设为1表示单次任务,然后在Quartz启动后,它会被立即执行,执行完成后,销毁!
用例:你可以在quartz调度中心里对外公开一些方法,让你的Job依赖于某个时间点和参数去执行,执行一次就停止,这样我们的调度就更加灵活了。
为单次任务添加了IsSingle属性
[DisallowConcurrentExecution()]
public abstract class JobBase : ISchedulingJob
{
#region Properties /// <summary>
/// 取消资源
/// </summary>
public CancellationTokenSource CancellationSource => new CancellationTokenSource(); /// <summary>
/// 执行计划,除了立即执行的JOB之后,其它JOB需要实现它
/// </summary>
public virtual string Cron => "* * * * * ?"; /// <summary>
/// 是否为单次任务,黑为false
/// </summary>
public virtual bool IsSingle => false; /// <summary>
/// Job的名称,默认为当前类名
/// </summary>
public virtual string JobName => GetType().Name; /// <summary>
/// Job执行的超时时间(毫秒),默认5分钟
/// </summary>
public virtual int JobTimeout => * * ; #endregion Properties #region Methods /// <summary>
/// Job具体类去实现自己的逻辑
/// </summary>
protected abstract void ExcuteJob(IJobExecutionContext context, CancellationTokenSource cancellationSource); /// <summary>
/// 当某个job超时时,它将被触发,可以发一些通知邮件等
/// </summary>
/// <param name="arg"></param>
private void CancelOperation(object arg)
{
CancellationSource.Cancel();
StdSchedulerFactory.GetDefaultScheduler().Result.Interrupt(new JobKey(JobName));
Console.WriteLine(JobName + "Job执行超时,已经取消,等待下次调度...");
} #endregion Methods #region IJob 成员 public Task Execute(IJobExecutionContext context)
{
Timer timer = null;
try
{
timer = new Timer(CancelOperation, null, JobTimeout, Timeout.Infinite);
Console.WriteLine(DateTime.Now.ToString() + "{0}这个Job开始执行", context.JobDetail.Key.Name);
if (context.JobDetail.JobDataMap != null)
{
foreach (var pa in context.JobDetail.JobDataMap)
Console.WriteLine($"JobDataMap,key:{pa.Key},value:{pa.Value}");
}
ExcuteJob(context, CancellationSource);
}
catch (Exception ex)
{
Console.WriteLine(this.GetType().Name + "error:" + ex.Message);
}
finally
{
if (timer != null) timer.Dispose();
}
return Task.CompletedTask;
} #endregion
}
统一的加入Job队列的方法
在我们之前的QuartzManager管理者中,我们需要添加对单次任务的支持,这点我们将任务加入到quartz的代码进行了重构,提取到了方法里。
/// <summary>
/// 将类型添加到Job队列
/// </summary>
/// <param name="type">类型</param>
/// <param name="dt">时间点</param>
/// <param name="param">参数</param>
private static void JoinToQuartz(Type type, DateTimeOffset dt, Dictionary<string, object> param = null)
{
var obj = Activator.CreateInstance(type);
if (obj is ISchedulingJob)
{
var tmp = obj as ISchedulingJob;
string cron = tmp.Cron;
string name = tmp.JobName;
var cancel = tmp.CancellationSource; var jobDetail = JobBuilder.Create(type)
.WithIdentity(name)
.Build();
if (param != null)
foreach (var dic in param)
jobDetail.JobDataMap.Add(dic.Key, dic.Value); ITrigger jobTrigger;
if (tmp.IsSingle)
{
jobTrigger = TriggerBuilder.Create()
.WithIdentity(name + "Trigger")
.StartAt(dt)
.Build();
}
else
{
jobTrigger = TriggerBuilder.Create()
.WithIdentity(name + "Trigger")
.StartNow()
.WithCronSchedule(cron)
.Build();
}
StdSchedulerFactory.GetDefaultScheduler().Result.ScheduleJob(jobDetail, jobTrigger, cancel.Token);
LoggerInfo($"->任务模块{name}被装载...", ConsoleColor.Yellow);
}
}
对外公开的参数化接口
而对于外界如果希望再次触发这个单次任务,我们可以在QuartzManager里公开一个方法,用来向当前SchedulerFactory里添加新的Job就可以了,这个方法很简单,可以提供一个默认的时间策略,如默认为1分钟后执行,也可以自己控制时间。
/// <summary>
/// 任务在1分钟之后被执行1次
/// </summary>
/// <param name="type"></param>
/// <param name="job"></param>
/// <param name="param"></param>
public static void SignalJob(Type type, Dictionary<string, object> param)
{
SignalJob(type, DateTimeOffset.Now.AddSeconds(), param);
} /// <summary>
/// 任务在某个时间之后被执行1次
/// </summary>
/// <param name="type"></param>
/// <param name="job"></param>
/// <param name="offset"></param>
/// <param name="param"></param>
public static void SignalJob(Type type, DateTimeOffset offset, Dictionary<string, object> param)
{
JoinToQuartz(type, offset);
}
那么,现在某个任务调度中心就更加完善了,开发人员在使用时也很简单,只要继承JobBase,或者去实现ISchedulingJob接口就可以了,非常灵活!
感谢各位的阅读!
quartz,dotnet core我们还在继续研究的路上!
DotNetCore跨平台~Quartz定时单次任务的更多相关文章
- DotNetCore跨平台~Quartz热部署的福音~监控文件夹的变化
在DotNetCore出来之后,同时也使用了quartz进行调度中心的设计,将它做到docker里方便部署,在之前的quartz版本里支持配置文件的方式,而现在不支持了,我们应该去想一下,为什么不去支 ...
- java 多线程——quartz 定时调度的例子
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
- 项目一:第十四天 1.在realm中动态授权 2.Shiro整合ehcache 缓存realm中授权信息 3.动态展示菜单数据 4.Quartz定时任务调度框架—Spring整合javamail发送邮件 5.基于poi实现分区导出
1 Shiro整合ehCache缓存授权信息 当需要进行权限校验时候:四种方式url拦截.注解.页面标签.代码级别,当需要验证权限会调用realm中的授权方法 Shiro框架内部整合好缓存管理器, ...
- Quartz定时调度框架
Quartz定时调度框架CronTrigger时间配置格式说明 CronTrigger时间格式配置说明 CronTrigger配置格式: 格式: [秒] [分] [小时] [日] [月] [周] [年 ...
- spring利用javamail,quartz定时发送邮件 <转>
原文地址:spring利用javamail,quartz定时发送邮件 <转>作者:物是人非 spring提供的定时发送邮件功能,下面是一个简单的例子以供大家参考,首先从spring配置文件 ...
- Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群
Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群 >>>>>>>>>>>>>> ...
- DotNetCore跨平台~文章索引~永久更新
本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet ...
- DotNetCore跨平台~Dapper的使用
回到目录 Dapper作为小型ORM的代表作品被我们应用到了dotnet core的项目中,下面将把自己在项目中使用dapper进行curd操作的过程写一下,后期可能会遇到一些问题,大叔也会在这个系列 ...
- DotNetCore跨平台~聊聊中间件
回到目录 在进行.net core平台之后,我们如果希望在请求过程中添加一些事件是非常容易的,你可以把这些事件做成一个中间件Middleware,然后这些中间件就会以Http pipeline的管道方 ...
随机推荐
- 【学习进步之路】-【浏览器兼容】透明背景图IE、360浏览器不兼容
最近在项目中遇到了浏览器兼容问题,透明背景图在IE或360兼容模式下没有效果,以前都是网上搜到结果,直接用了,并没有深入的去理解和利用,总会在下一次使用的时候忘记.为了让自己在前端方面学习更有成效,想 ...
- Java常用文件操作-1
在我们的实际工作中经常会用到的文件操作,再此,将工作中碰到的做一个记录,以便日后查看. 1.复制文件夹到新文件夹下 /** * 复制文件夹下所有文件到指定路径 *@param oldPath *@pa ...
- Python爬虫从入门到放弃(二十三)之 Scrapy的中间件Downloader Middleware实现User-Agent随机切换
总架构理解Middleware 通过scrapy官网最新的架构图来理解: 这个图较之前的图顺序更加清晰,从图中我们可以看出,在spiders和ENGINE提及ENGINE和DOWNLOADER之间都可 ...
- HTML中的target标记
HTML:target=_blank -- 在新窗口中打开链接 _parent -- 在父窗体中打开链接 _self -- 在当前窗体打开链接,此为默认值 _top -- 在当前窗体打开链接,并替换当 ...
- TestNG的组测试和组中组测试
在编写测试的过程中,我们经常遇到只想执行个别或者某一部分/某一类型的测试用例,这时我们可以使用TestNG的分组测试方法 分组测试在配置时,TestNG执行的原则是:只保留最小集合进行执行 看代码: ...
- 小A点菜 洛谷 p1164
题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家--餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:"随便点". 题目描述 不过ui ...
- HTML5的三种存储方式以及区别
首先将存储方式前要先知道为什么要使用他:一是利用本地数据,介绍网络请求:二是弱网环境下,高延迟,低带宽,要把数据本地化: 1.本地存储localStorage和sessionStorage 介绍: 存 ...
- Markdown几个简单的例子
定义型列表 语法说明: 定义型列表由名词和解释组成.一行写上定义,紧跟一行写上解释. 解释的写法:紧跟一个缩进(Tab) Markdown : 轻量级文本标记语言,可以转换成html,pdf等格式(左 ...
- 英文面试&笔试
Topics:1.Talk about your carreer plan2.In ten years, what kind of people you will be? At that time,w ...
- [UWP]了解模板化控件(5.1):TemplatePart vs. VisualState
1. TemplatePart vs. VisualState 在前面两篇文章中分别使用了TemplatePart及VisualState的方式实现了相同的功能,其中明显VisualState的方式更 ...