原文:作业调度框架Quartz.NET | 大专栏

作业调度框架Quartz.NET


发表于
2019-09-28



分类于

前端


没有评论

前言

任务调度系统并不是完美的,它会出现任务执行失败的情况。如果你需要处理任务失败后的逻辑,希望这篇笔记可以为你提供些帮助。
Quartz.NET的任务监听系统已经被我运用在已上线的工程中,亲测无坑。

Quartz.Listener

要创建一个监听器,只需创建一个实现ITriggerListener或IJobListener接口的对象。然后在运行时向调度程序注册监听器,并且必须为其指定名称(更确切地说,他们必须通过其Name属性来唯一标识自己。)

关键接口和类

  • IJobListener - 与作业相关的事件包括:作业即将执行的通知,以及作业完成执行时的通知。
  • ITriggerListener - 与触发器相关的事件包括:触发器触发,触发错误触发和触发器完成(触发器触发的作业完成)。
  • ListenerManager - 监听器与调度程序的ListenerManager一起注册,并附带一个Matcher,用于描述监听器想要接收事件的作业/触发器。

示例应用程序

using Quartz;
using Quartz.Impl;
using Quartz.Impl.Matchers;
using System;
using System.Collections.Specialized;
using System.Threading;
using System.Threading.Tasks; namespace QuarzLis
{
class Program
{
static void Main(string[] args)
{
StartUpJobs.StartUp().GetAwaiter().GetResult();
Console.ReadKey();
} public static class StartUpJobs
{
public static async Task StartUp()
{
try
{
//第一步:从工厂中获取Scheduler实例
NameValueCollection props = new NameValueCollection();
StdSchedulerFactory factory = new StdSchedulerFactory(props);
IScheduler scheduler = await factory.GetScheduler();
//第二步:然后运行它
await scheduler.Start();
//第三步:定义作业并绑定到HelloJob类,HelloJob类实现IJob接口
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("job1", "group1")
//UsingJobData 可以用来传参数
.UsingJobData("appKey", "123456QWE")
.UsingJobData("appName", "小熊猫")
.UsingJobData("api", "https://www.baidu.com")
.Build(); //第四步:创建触发器。设定,执行一次作业。
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1") //指定唯一标识,触发器名字,和组名字
//这对于将作业和触发器组织成“报告作业”和“维护作业”等类别非常有用。
//作业或触发器的键的名称部分在组内必须是唯一的
.StartAt(DateBuilder.FutureDate(5, IntervalUnit.Second)) //可以设定在未来的 5 秒钟后触发
.Build(); //第五步:作业与触发器组合,安排任务
await scheduler.ScheduleJob(job, trigger); //第六步:创建任务监听,用来解决任务执行失败的情况. HelloJob类实现IJobListener接口
IJobListener jobListener = new HelloJob(); // 注: 任务监听是通过 IJobListener.Name 来区分的.以下逻辑避免多个任务监听情况下造成的监听被覆盖.
// a) 获取当前任务监听实例的名称.
var listener = scheduler.ListenerManager.GetJobListener(jobListener.Name);
// b) 通过job.Key 获取该任务在调度系统中的唯一实体
IMatcher<JobKey> matcher = KeyMatcher<JobKey>.KeyEquals(job.Key);
// c) 注意: 任务监听系统中已存在当前任务监听实例,与新添加任务监听的逻辑的区别.
if (listener != null)
{
// 如果已存在该任务监听实例,调用此方法,为该任务监听实例新增监听对象
scheduler.ListenerManager.AddJobListenerMatcher(jobListener.Name, matcher);
}
else
// 任务监听系统中不存在该任务监听实例,则调用此方法新增监听对象
scheduler.ListenerManager.AddJobListener(jobListener, matcher); //创建触发器监听,触发器监听与任务监听同名也不影响
ITriggerListener triggerListener = new HelloJob();
var triListener = scheduler.ListenerManager.GetTriggerListener(triggerListener.Name);
IMatcher<TriggerKey> triMatcher = KeyMatcher<TriggerKey>.KeyEquals(trigger.Key);
if (triListener != null)
{
scheduler.ListenerManager.AddTriggerListenerMatcher(triggerListener.Name, triMatcher);
}
else
scheduler.ListenerManager.AddTriggerListener(triggerListener, triMatcher); //可以设置关闭该调度
//await Task.Delay(TimeSpan.FromSeconds(5));
//await scheduler.Shutdown();
}
catch (SchedulerException se)
{
Console.WriteLine(se);
}
}
} //实现IJobListener 接口,实现 ITriggerListener 接口,这里和 IJob逻辑放在了一起
public class HelloJob : IJob, IJobListener, ITriggerListener
{
private string appKey;
private string appName;
private string appApi; public string Name
{
get;
}
public HelloJob()
{
this.Name = this.GetType().ToString();
}
public HelloJob(string name)
{
this.Name = name;
}
public async Task Execute(IJobExecutionContext context)
{
JobKey jkey = context.JobDetail.Key;
TriggerKey tKey = context.Trigger.Key; JobDataMap dataMap = context.MergedJobDataMap;
appKey = dataMap.GetString("appKey"); //通过键值获取数据
appName = dataMap.GetString("appName");
appApi = dataMap.GetString("api");
await Console.Error.WriteLineAsync(
string.Format("[{0}]开始推送:nJobKey:{1}nTriggerKey:{2}nAppKey:{3} appName: {4} , and AppAPI: {5}"
, DateTime.Now.ToLongTimeString(), jkey, tKey, appKey, appName, appApi));
}
#region IJobListener
public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Console.Error.WriteLineAsync(string.Format("[{0}]任务监听,name:{1}|任务执行失败重新执行。"
, DateTime.Now.ToLongTimeString(), Name));
//任务执行失败,再次执行任务
await Execute(context);
} public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Console.Error.WriteLineAsync(string.Format("[{0}]任务监听,name:{1}|准备执行任务。"
, DateTime.Now.ToLongTimeString(), Name));
} public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default(CancellationToken))
{
await Console.Error.WriteLineAsync(string.Format("[{0}]任务监听,name:{1}|任务执行完成。"
, DateTime.Now.ToLongTimeString(), Name));
}
#endregion #region ITriggerListener
public async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default(CancellationToken))
{
await Console.Error.WriteLineAsync(string.Format("[{0}]触发器监听,name:{1}|触发器触发成功。"
, DateTime.Now.ToLongTimeString(), trigger.Key.Name));
} public async Task TriggerFired(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Console.Error.WriteLineAsync(string.Format("[{0}]触发器监听,name:{1}|触发器开始触发。"
, DateTime.Now.ToLongTimeString(), trigger.Key.Name));
} public async Task TriggerMisfired(ITrigger trigger, CancellationToken cancellationToken = default(CancellationToken))
{
await Console.Error.WriteLineAsync(string.Format("[{0}]触发器监听,name:{1}|触发器触发失败。"
, DateTime.Now.ToLongTimeString(), trigger.Key.Name));
} public async Task<bool> VetoJobExecution(ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default(CancellationToken))
{
await Console.Error.WriteLineAsync(string.Format("[{0}]触发器监听,name:{1}|可以阻止该任务执行,这里不设阻拦。"
, DateTime.Now.ToLongTimeString(), trigger.Key.Name));
// False 时,不阻止该任务。True 阻止执行
return false;
}
#endregion
}
}
}

实验效果

如截图所示,这里只执行一次。注意观察:触发器监听优先级 > 任务监听优先级

上篇

上篇:作业调度框架Quartz.NET-01-快速入门

Thanks

Quartz.NET

张善友的博客


未找到相关的 Issues 进行评论

请联系 @Replay923 初始化创建

使用 GitHub 登录

作业调度框架Quartz.NET | 大专栏的更多相关文章

  1. 作业调度框架Quartz.NET-现学现用-01-快速入门

    原文:作业调度框架Quartz.NET-现学现用-01-快速入门 前言 你需要应用执行一个任务吗?这个任务每天或每周星期二晚上11:30,或许仅仅每个月的最后一天执行.一个自动执行而无须干预的任务在执 ...

  2. 作业调度框架Quartz.NET-现学现用-01-快速入门 - 简书

    原文:作业调度框架Quartz.NET-现学现用-01-快速入门 - 简书 前言 你需要应用执行一个任务吗?这个任务每天或每周星期二晚上11:30,或许仅仅每个月的最后一天执行.一个自动执行而无须干预 ...

  3. 作业调度框架Quartz.NET-现学现用-02-任务监听

    原文:作业调度框架Quartz.NET-现学现用-02-任务监听 前言 任务调度系统并不是完美的,它会出现任务执行失败的情况.如果你需要处理任务失败后的逻辑,希望这篇笔记可以为你提供些帮助. Quar ...

  4. 作业调度框架Quartz.NET-现学现用-02-任务监听 - 简书

    原文:作业调度框架Quartz.NET-现学现用-02-任务监听 - 简书 前言 任务调度系统并不是完美的,它会出现任务执行失败的情况.如果你需要处理任务失败后的逻辑,希望这篇笔记可以为你提供些帮助. ...

  5. 作业调度框架 Quartz.NET 2.0 StepByStep

    注:目前网上诸多介绍Quartz.net的文章,甚至Quartz.net官网上的Tutorial都是1.0版本的,而这个项目在2.0版本对项目进行了比较大规模的修改,使得原有的很多例子都不能运行,故写 ...

  6. .Net平台开源作业调度框架Quartz.Net

    Quartz.NET介绍: Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中. ...

  7. (转).Net平台开源作业调度框架Quartz.Net

    Quartz.NET介绍: Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中. ...

  8. .NET开源作业调度框架(Quartz.NET和FluentScheduler)实战项目演练

    一.课程介绍 明人不说暗话,跟着阿笨一起玩NET .本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享 ...

  9. java作业调度框架Quartz

    在软件开发中,很多时候需要在特定时间的时间执行某些操作,比如每天的凌晨三点.每周的周日.每个月的15号,Apache Quartz就是一个开源的作业调度框架,可以让计划的程序任务一个预定义的日期和时间 ...

随机推荐

  1. vue-element-admin 实现动态路由(从后台查询出菜单列表绑定)

    1. 在路由实例中保留基础路由 router/index.js中只需要保留基础路由,其他的都删了 2. 获取用户菜单,并保存到Vuex中 stroe/modules/user.js中,有个getInf ...

  2. 【00NOIP普及组】税收与补贴问题(信息学奥赛一本通 1911)( 洛谷 1023)

    [题目描述] 每样商品的价格越低,其销量就会相应增大.现已知某种商品的成本及其在若干价位上的销量(产品不会低于成本销售),并假设相邻价位间销量的变化是线性的且在价格高于给 定的最高价位后,销量以某固定 ...

  3. [RoarCTF]Easy Java

    目录 [RoarCTF]Easy Java 知识点 1.WEB-INF/web.xml泄露 [RoarCTF]Easy Java 题目复现链接:https://buuoj.cn/challenges ...

  4. idea乱码问题

    ## 1. 文件中内容中文乱码 这个原因是文件的编码和项目的编码不一致导致,将项目工程和文件的编码设置成一致的(如,文件编码是GBK,那就都设置为GBK,若为UTF-8就都设置为UTF-8) ## 2 ...

  5. SSM项目实战 之 Maven

    目录 Maven 简介 Maven是什么 Maven下载安装 Maven使用 Maven规定了一套默认的项目格式 创建第一个Maven项目 Maven仓库 Maven常用命令 Maven作用范围(sc ...

  6. 秒杀功能压测 jmeter----------windows系统运行jmeter遇到的坑

    最近做了一个安全传输模块,因为怕对性能有较大影响,因此测试安排了针对性的压测 压测的过程出现了一点小问题 发现失败率特别高,测试怀疑是服务端出了错,但是我查看日志发现没有报错.后面我观察TCP链接数排 ...

  7. android -------- SHA 加密算法

    安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法.能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的 ...

  8. php中heredoc与nowdoc的使用方法、定界符<<<的使用方法

    一.heredoc结构及用法 Heredoc 结构就象是没有使用双引号的双引号字符串,这就是说在 heredoc 结构中单引号不用被转义.其结构中的变量将被替换,但在 heredoc 结构中含有复杂的 ...

  9. EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器前端源码重构(六)- webpack-dev-server 自适应支持手机端访问

    关于EasyDSS EasyDSS商用流媒体服务器解决方案是一套集流媒体点播.转码与管理.直播.录像.检索.时移回看于一体的一套完整的商用流媒体服务器解决方案,EasyDSS高性能RTMP流媒体服务器 ...

  10. 10分钟弄懂Raft算法

    分布式系统在极大提高可用性.容错性的同时,带来了一致性问题(CAP理论).Raft算法能够解决分布式系统环境下的一致性问题. 我们熟悉的ETCD注册中心就采用了这个算法:你现在看的这篇微信公众号文章, ...