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 => 5 * 60 * 1000; #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(10), 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
分类:
.Net Core
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
2016-09-15 Lind.DDD.Domain.ISortBehavor~上移与下移
2014-09-15 爱上MVC~为非法进行Action的用户提供HttpStatusCodeResult
2011-09-15 浅拷贝在项目中的应用