原文:作业调度框架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. 设置多个className

    有时候我们需要有选择地设置多个className function myComponent(props) { const myClassName = { 'aaa', {'bbb': props.ne ...

  2. 第12组 Beta冲刺(3/5)

    Header 队名:To Be Done 组长博客 作业博客 团队项目进行情况 燃尽图(组内共享) 展示Git当日代码/文档签入记录(组内共享) 注: 由于GitHub的免费范围内对多人开发存在较多限 ...

  3. 数据结构---公交线路提示系统(Java后台+excel表格+web前端)

     系统大致流程: index.jsp输入站名(点击“出示站点信息”,跳转list.jsp读取表格):后台通过站名获得id:getIdbyname(String name)将id反馈至dijkstra( ...

  4. ICEM-结构化网格interface的做法

    原视频下载地址:http://yunpan.cn/cLHTCfRVNmihZ  访问密码 2ead

  5. mariadb 10.2/mysql 8.0实现递归

    借助mysql 8.0的cte(它是iso sql标准的一部分),可以实现递归,mariadb 10.2.2开始支持递归cte,如下: +----+----------+--------------+ ...

  6. XCode教程之 如何在苹果开发者平台添加设备UDID

    XCode教程之 如何在苹果开发者平台添加设备UDID.在Xcode开发中,如何在苹果开发者平台添加新的手机设备UDID,进行测试,具体如下 工具/原料 Apple Developer 方法/步骤 1 ...

  7. Redis 密码设置 及 带密码访问

    转: Redis 密码设置 如果不加密码,默认只能本机访问,加密码也是为了安全考虑 1.进入Redis 的安装目录,找到redis.conf文件.用vi命令打开文件 输入  / requirepass ...

  8. LD SCore计算基因多效性、遗传度、遗传相关性(the LD Score regression intercept, heritability and genetic correlation)

    这篇文章是对之前啊啊救救我,为何我的QQ图那么飘(全基因组关联分析)这篇文章的一个补坑. LD SCore除了查看显著SNP位点对表型是否为基因多效性外,还额外补充了怎么计算表型的遗传度和遗传相关性. ...

  9. [LeetCode] 73. Set Matrix Zeroes 矩阵赋零

    Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place. Exampl ...

  10. linux : 各个发行版中修改python27默认编码为utf-8

    该方法可解决robot报错:'ascii' codec can't encode character u'\xf1' in position 16: ordinal not in  range(128 ...