DotNetCore跨平台~Quartz定时单次任务

之前写过一篇文件《DotNetCore跨平台~Quartz热部署的福音~监控文件夹的变化》,今天主要把框架优化了一下,支持外部触发,并支持外部将参数以JobDataMap形式进行输入,然后在咱们的Job里进行使用它,故称参数化任务。

Quartz使用场景:

  1. 定时单次任务:在未来某个时间去执行一次
  2. 定点任务  :在某个时间去执行,可以是轮询的
  3. 周期任务  :按某个时间间隔去轮询执行

今天说的外部触发的任务是指第一种,即在未来某个时间点去执行,并且只执行一次。说一下思路,这种任务某个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我们还在继续研究的路上!

时间: 2024-10-08 09:46:25

DotNetCore跨平台~Quartz定时单次任务的相关文章

DotNetCore跨平台~Quartz热部署的福音~监控文件夹的变化

回到目录 在DotNetCore出来之后,同时也使用了quartz进行调度中心的设计,将它做到docker里方便部署,在之前的quartz版本里支持配置文件的方式,而现在不支持了,我们应该去想一下,为什么不去支持配置文件?当然大叔也为配置文件设计了支持的方式,但我们还是应该想想作者为什么不去支持配置? 热支持,服务发现? 和上面两个概念可能有点关系,热插拔很容易理解,就是把dll模块放到正在运行的项目时,它可以直接启动,这个功能对调度中心来说,很是必要,因为你可能需要按着不同的功能设计一些服务j

java 多线程——quartz 定时调度的例子

java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 java 多线程—— 线程等待与唤醒 概述 第1部分 配置 第2部分 代码示例 第1部分 配置 有关quartz的api文档地址:Quartz Enterprise Job Scheduler 1.8.6 API 主要接口目录: 重点看下Job,Scheduler,Trigger,JobDetai

项目一:第十四天 1.在realm中动态授权 2.Shiro整合ehcache 缓存realm中授权信息 3.动态展示菜单数据 4.Quartz定时任务调度框架—Spring整合javamail发送邮件 5.基于poi实现分区导出

1 Shiro整合ehCache缓存授权信息 当需要进行权限校验时候:四种方式url拦截.注解.页面标签.代码级别,当需要验证权限会调用realm中的授权方法   Shiro框架内部整合好缓存管理器,整合ehcache环境,只需要配置即可.     <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>

Spring整合Quartz定时发送邮件

功能描述:刚开始接触Quartz,试着用Quartz整合spring实现每隔一分钟发送一封邮件连续发送10次 核心jar: 邮件发送:commons-email-1.2.jar mail.jar(必须的) quartz:quartz-all-1.8.3.jar quartz-all-1.8.3/lib/下所有jar spring:spring-context-support.ajr(必须的) 只贴出核心代码: Email发送:使用apache commons-email跟mail package

Quartz定时任务调度机制解析(CronTirgger、SimpleTrigger )

一.Quartz的介绍 Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现.该项目于 2009 年被 Terracotta 收购,目前是 Terracotta 旗下的一个项目.它是一个而安全有java辨析额的开源作业调度框架. 二.Quartz 具有以下特点 1.强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求: 2.灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式: 3.分布式和集群能力,

quartz定时

字段允许值允许的特殊字符 秒 0-59 , - * / 分 0-59 , - * / 小时 0-23 , - * / 日期 1-31 , - * ? / L W C 月份 1-12 或者 JAN-DEC , - * / 星期 1-7 或者 SUN-SAT , - * ? / L C # 年(可选)留空, 1970-2099 , - * / 表达式意义 "0 0 12 * * ?" 每天中午12点触发 "0 15 10 ? * *" 每天上午10:15触发 "

DotNetCore跨平台~问题~NETCoreAPP, Version=v1.0&#39; compatible with one of the target runtimes: &#39;win10-x64

回到目录 新建console项目之后,编译程序出现以下错误: Can not find runtime target for framework '.NETCoreAPP, Version=v1.0' compatible with one of the target runtimes: 'win10-x64, win81-x64, win8-x64, win7-x64'. Possible causes:        The project has not been restored or

DotNetCore跨平台~文章索引~永久更新

本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet core越来越好,希望2.0正式版快点出来! DotNetCore跨平台目录 DotNetCore跨平台~Startup类的介绍(2016-05-31 16:25) Linux~centos上安装.netcore,HelloWorld归来!(2016-09-05 13:25) .NetCore~框

DotNetCore跨平台~聊聊中间件

回到目录 在进行.net core平台之后,我们如果希望在请求过程中添加一些事件是非常容易的,你可以把这些事件做成一个中间件Middleware,然后这些中间件就会以Http pipeline的管道方式进行相应,并且它们就像是一个职责链,从你定义的第一个中间件开始,一个一个向下传递,直到最后一个中间件完成为止! 前几天我写了在.net core里实现模块化服务,DotNetCore跨平台~组件化时代来了主要是将我们定义的组件添加到IServiceCollection集合里,然后在程序启动后去注册