Ø  前言

前两天,在公司的一个项目中编写 Windows 服务时,需求是当A服务运行完后,B服务才能运行,B服务运行后,C服务才能运行。因为B服务的数据依赖于A服务生成的数据,而C服务的数据又依赖于B服务。

在之前的文章中有介绍使用 Topshelf 结合 Quartz.NET 创建 Windows 服务,但是当时还不涉及这样的需求,经过后面看过一些相关博客后,便实现了该功能。另外,这里再写个 Demo 研究了一下。

Ø  假设我们有这样一个需求:

1.   就上一篇使用 Topshelf 结合 Quartz.NET 创建 Windows 服务而言,当我们更新商品库存后,我们需要发送短信和邮件通知管理员。

2.   而这两个动作都是两个独立的服务作业,并且它们都相互依赖。

3.   执行顺序:更新商品库存 -> 发送短信 -> 发送邮件,三者都是前一个服务执行完后,接着执行下个服务,下面是具体实现步骤。

1.   首先,我们定义服务配置文件quartz_jobs.xml

<!--该作业用于定时更新商品库存-->

<job>

<name>UpdateInventoryJob</name>

<group>JobGroup1</group>

<description>定时更新商品库存</description>

<job-type>TopshelfAndQuartz.UpdateInventoryJob,TopshelfAndQuartz</job-type>

<durable>true</durable>

<recover>false</recover>

</job>

<trigger>

<cron>

<name>UpdateInventoryTrigger</name>

<group>UpdateInventoryTriggerGroup</group>

<job-name>UpdateInventoryJob</job-name>

<job-group>JobGroup1</job-group>

<start-time>2017-12-01T00:00:00+08:00</start-time>

<cron-expression>0 0/1 * * * ?</cron-expression>

</cron>

</trigger>

<!--该作业用于发送短信-->

<job>

<name>SendSMSJob</name>

<group>JobGroup1</group>

<description>发送短信作业</description>

<job-type>TopshelfAndQuartz.SendSMSJob,TopshelfAndQuartz</job-type>

<durable>true</durable>

<recover>false</recover>

</job>

<trigger>

<cron>

<name>SendSMSJobTrigger</name>

<group>SendSMSJobTriggerGroup</group>

<job-name>SendSMSJob</job-name>

<job-group>JobGroup1</job-group>

<start-time>2027-12-01T00:00:00+08:00</start-time>

<cron-expression>0 0/1 * * * ?</cron-expression>

</cron>

</trigger>

<!--该作业用于发送邮件-->

<job>

<name>SendMailJob</name>

<group>JobGroup1</group>

<description>发送邮件作业</description>

<job-type>TopshelfAndQuartz.SendMailJob,TopshelfAndQuartz</job-type>

<durable>true</durable>

<recover>false</recover>

</job>

<trigger>

<cron>

<name>SendMailJobTrigger</name>

<group>SendMailJobTriggerGroup</group>

<job-name>SendMailJob</job-name>

<job-group>JobGroup1</job-group>

<start-time>2027-12-01T00:00:00+08:00</start-time>

<cron-expression>0 0/1 * * * ?</cron-expression>

</cron>

</trigger>

1)   可以发现,这里将作业分组名称都命名为“JobGroup1”,这是为了将这三个作业加入作业链中,需要将它们分为同一组中。

2)   另外,为了防止 SendSMSJob、SendMailJob 在服务启动后自动执行,将<start-time>节点设置成了2027-12-01T00:00:00+08:00,因为不希望它们自动执行。

2.   定义发送短信、发送邮件作业(这里只是简单打印执行日志)

/// <summary>

/// 发送短信作业。

/// </summary>

public class SendSMSJob : IJob

{

/// <summary>

/// 作业被触发时执行该方法。

/// </summary>

public void Execute(IJobExecutionContext context)

{

Log.Logger.Info("开始执行发送短信作业");

}

}

/// <summary>

/// 发送邮件作业。

/// </summary>

public class SendMailJob : IJob

{

/// <summary>

/// 作业被触发时执行该方法。

/// </summary>

public void Execute(IJobExecutionContext context)

{

Log.Logger.Info("开始执行发送邮件作业");

}

}

3.   配置作业监听程序

/// <summary>

/// 配置作业监听。

/// </summary>

public static void ConfigureJobListener()

{

ISchedulerFactory factory = new StdSchedulerFactory();

IScheduler scheduler = factory.GetScheduler();

JobChainingJobListener listener = null;

//创建作业Key(名称与分组)

JobKey uiJobKey = JobKey.Create("UpdateInventoryJob", "JobGroup1");

JobKey sendSmsJobKey = JobKey.Create("SendSMSJob", "JobGroup1");

JobKey sendMailJobKey = JobKey.Create("SendMailJob", "JobGroup1");

//设置作业监听链

listener = new JobChainingJobListener("链接更新库存、发送短信、发送邮件作业");

listener.AddJobChainLink(uiJobKey, sendSmsJobKey);

listener.AddJobChainLink(sendSmsJobKey, sendMailJobKey);

scheduler.ListenerManager.AddJobListener(listener,

GroupMatcher<JobKey>.GroupEquals("JobGroup1"));

}

4.   在服务运行前加入作业监听

Log.Logger.Info("服务开始运行");

ConfigureJobListener(); //配置作业监听

HostFactory.Run(o =>

{

//o.UseLog4Net(); //这里需要使用 log4net, Version=1.2.15.0 的版本,当前版本不兼容所以注释掉

o.Service<ServiceRunner>();

o.SetServiceName("TopshelfAndQuartzService");

o.SetDisplayName("库存更新服务");

o.SetDescription("该服务用于定时更新商品库存");

o.EnablePauseAndContinue();

});

5.   这样,我们作业监听链就配置好了,运行效果:

Ø  总结

1.   其实 Quartz.NET 的功能还是很强大,它支持多个作业或触发设置监听,并可以自定义作业监听(实现 IJobListener 接口)或触发器监听(实现 ITriggerListener 接口),有兴趣的朋友可以深入研究。

2.   可参考文章:

1)   https://www.cnblogs.com/linzhao126/p/4528519.html

2)   http://www.cnblogs.com/zhangzhi19861216/p/4756610.html

3)   https://www.quartz-scheduler.net/documentation/index.html

使用 Quartz.NET 实现作业串行执行的更多相关文章

  1. spring定时器任务多任务串行执行问题排查

    最近发现个生产问题,定时器任务某些任务没有及时执行.经过研究排查发现spring 定时器任务scheduled-tasks默认配置是单线程串行执行的,这就造成了若某个任务执行时间过长,其他任务一直在排 ...

  2. 背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知)

    [源码下载] 背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知) 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 ...

  3. oracle中并行执行不一定比串行执行快

    并行执行与串行执行相比,能否缩短执行时间,取决于如下几个方面:1.待执行的目标SQL是否适合并行执行,有些SQL是不太适合并行执行的,比如走索引的嵌套循环连接.2.数据库服务器上的硬件资源(如CPU. ...

  4. NodeJs使用async让代码按顺序串行执行

    描述 由于nodejs中的函数调用都是异步执行的,而笔者在工程开发中函数A需要四五个参数,而这四五个参数值都是通过函数调用获得,因此按顺序写代码时,执行到函数A时,往往函数A需要的参数值因为参数的异步 ...

  5. jenkins 多任务串行执行

    摘要 今天在新创建自动化部署项目的时候遇到了一个问题:我们的项目是maven聚合的所以在构建maven项目的时候要从parent开始build,但是这样会造成一个问题,我每次添加此parent项目下的 ...

  6. loadrunner多场景的串行执行以及定时执行

    方法一: 既然是脚本串行执行,那在场景设计中必然是要用多个脚本,要注意的是需要将Scenario Schedule中的Schedule by设置为Group的模式.然后按实际需要依次设置每个脚本的Sc ...

  7. SpringBoot中定时任务默认是串行执行 如何设置并行

    SpringBoot项目中,定时任务默认是串行执行的,不论启动多少任务,都是一个执行完成,再执行下一个. 如何设置并行呢? @EnableAsync  和@Async 这两个注解来实现 ,具体如下: ...

  8. 任意promise串行执行算法 - 童彪

      // 任意promise串行执行算法 - 童彪 function runAllPromise() { var p1 = new Promise((resove, reject) => { s ...

  9. 【Nodejs】nimble或async并不能保证程序串行执行,回调是回避不了的坑

    先看一段例程: //------------------------------- // 用于创建目录 //------------------------------- function creat ...

随机推荐

  1. 「POJ3696」The Luckiest number【数论,欧拉函数】

    # 题解 一道数论欧拉函数和欧拉定理的入门好题. 虽然我提交的时候POJ炸掉了,但是在hdu里面A掉了,应该是一样的吧. 首先我们需要求的这个数一定可以表示成\(\frac{(10^x-1)}{9}\ ...

  2. 用c#查询各快递物流信息

    前面介绍过<用快递100接口查询各快递物流信息>,里面用的是API接口,但有些快递不支持这种方式,本文介绍的HtmlAPI支持所有快递公司. 支持包括EMS.邮政.顺丰和申通在内的所有公司 ...

  3. 2018-2019 ACM-ICPC Pacific Northwest Regional Contest C Contest Setting(DP)

    比赛链接:Contest Setting C题 题意:$n$道题目,每道题目难度为$ai$,选择$k$道难度不同的题目,有多少种选择方案.$1<=k<=n<=1000,1<=a ...

  4. LOJ#6285. 数列分块入门 9

    有点难..... 要求区间众数,所以我可以先把区间分块,然后我预处理出从第 i 块到第 j 块的众数,用dp[i][j]记录下来. 因为需要知道众数的num值, 所以我可以用一个vector来保存每个 ...

  5. centos7安装Jenkins更改默认端口并配置Ldap服务器进行用户认证

    应用环境:Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作.   Jenkins官网:https://jenkins.io/ 测试环境:一台Centos ...

  6. JavaScript ES6 核心功能一览

    JavaScript 在过去几年里发生了很大的变化.这里介绍 12 个你马上就能用的新功能. JavaScript 历史 新的语言规范被称作 ECMAScript 6.也称为 ES6 或 ES2015 ...

  7. C#串口通信:2自动连接

    上次说到了协议的大致结构,这次我们来说说怎么去实现制动连接串口(当你把设备连上来之后,怎么去让软件自动去识别是否为目标设备,当然这需要上位机与下位机共同完成,这里我们只讨论上位机部分)先上协议: 帧头 ...

  8. TestNg 9. 参数化测试-DataProvider参数化

    首先利用@DataProvider(name = "XXX")的属性,将name的值XXX 传递给 @Test(dataProvider = "XXX") 看以 ...

  9. java基础学习2

    http://www.runoob.com/java/java-modifier-types.html   Java 修饰符 Java 增强 for 循环 Java5 引入了一种主要用于数组的增强型 ...

  10. HDU 1560 DNA sequence (迭代加深搜索)

    The twenty-first century is a biology-technology developing century. We know that a gene is made of ...