[更新] 基于Quartz.NET 的任务调度管理工具

 

更新列表:

  1. 任务参数可视化.
  2. 立即中断正在执行的任务.
  3. 每个任务独立的应用程序域

上一版参见:

基于Quqrtz.NET 做的任务调度管理工具

界面具体变化如下:

任务参数可视化

如上图所示, 在管理任务的界面上就可以知道这个任务需哪些参数/类型 及 参数的说明.

实现方式, 在 Job 上添加 特性 :  ParameterTypeAttribute

 1 namespace JobA {
2 [ParameterType(typeof(Parameter))]
3 public class Job : IJob {
4
5 public static ILog Log = LogManager.GetLogger(typeof(Job));
6 public void Execute(IJobExecutionContext context) {
7 var dataMap = context.JobDetail.JobDataMap;
8 //if (dataMap.ContainsKey("int")) {
9 // var pInt = dataMap.GetIntValue("int");
10 // Console.WriteLine("1 JobA Parameter {0}", pInt);
11 //} else {
12 // Log.Error("缺少参数 int, 未执行");
13 // throw new JobExecutionException("缺少参数");
14 //}
15
16 var p = dataMap.Parse<Parameter>();
17 Console.WriteLine("{0}\t{1}\t{2}\t{3}", p.PDateTime, p.PDecimal, p.PInt, p.PNullableInt);
18
19
20 Thread.Sleep(TimeSpan.FromMinutes(3));
21 }
22 }
23 }

取参数直接调用 dataMap.Parse<Parameter>() 就行了.

Parse 方法在: QM.Common. DatamapParser 中定义.

相比原始的从 DataMap 中用 key / value 方法取参数, 这种处理方式的好处不言而喻.

但是也有缺点, DataMap 支持任何可序列化的类型,

而用这种方法只支持

string, decimal, long, int, single, double, DateTime, DateTimeOffset, TimeSpan , bool, char 这些类型. (没有做更深一步的处理, 有兴趣的,可以尝试自己去实现.)

每个任务独立的应用程序域

试想一下插件式开发, 如果你做的插件需要N个第三方DLL, 而这些DLL并没有引用到主项目上, 怎么办呢? 一堆的 FileLoadException, FileNotFoundException 等错误, 想想都头疼.

如果你开发的插件想拥有自己的配置文件, 又该怎么办呢? 自己实现一个配置文件读取解析? ini ? xml ? 头疼吧.

针对上面的问题, 在这里的最佳解决办法是 : 独立的应用程序域.

这个要从 IScheduler.JobFactory 说起.

在QM.Server.QMServer 的构造方法中, 指定 Schedule.JobFactory 为 IsolatedJobFactory

IsolatedJobFactory 的定义:

 1     public class IsolatedJobFactory : IJobFactory {
2
3 public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) {
4 return NewJob(bundle.JobDetail.JobType);
5 }
6
7 private IJob NewJob(Type jobType) {
8 return new IsolatedJob(jobType);
9 }
10
11 public void ReturnJob(IJob job) {
12 IDisposable disposable = job as IDisposable;
13 if (disposable != null) {
14 disposable.Dispose();
15 }
16 }
17 }

从 NewJob 方法上可以看出, 实例出来的 Job 并不是最终要执行的 Job, 而是 IsolatedJob 的实例, 它类似中间人的身份.

IsolatedJob 实现了 IInterruptableJob 接口, 为中断执行中的任务埋下伏笔.

在 IsolatedJob 的构造方法中, 通过 IsolateDomainLoader 新建一个应用程序域:

IsolatedDomainLoader 的构造函数:

 1 public IsolateDomainLoader(string path, string configFileName = "") {
2 AppDomainSetup setup = new AppDomainSetup();
3 setup.ApplicationName = "IsolateDomainLoader";
4 setup.ApplicationBase = path;
5 setup.DynamicBase = path;
6 setup.PrivateBinPath = path;
7 setup.CachePath = setup.ApplicationBase;
8 setup.ShadowCopyFiles = "true";
9 setup.ShadowCopyDirectories = setup.ApplicationBase;
10 if (!string.IsNullOrWhiteSpace(configFileName)) {
11 setup.ConfigurationFile = configFileName;
12 setup.ConfigurationFile = Path.Combine(path, configFileName);
13 }
14 this.Domain = AppDomain.CreateDomain("ApplicationLoaderDomain", null, setup);
15 }

参数 path 即最终要执行的 job 所在的 dll 的路径.

configFileName 即独立的配置文件名称.

这样一来, 一个 job 一个文件夹, 文件夹内放置这个 job 相关的DLL和配置文件, 和主程序完全隔离开来.

上面说 IsolatedJob 是个中间人, 这里解释一下:

1, IsolatedJobFactory 的 NewJob 方法返回的是 IsolatedJob 的实例, 而不是最终要执行的 Job.

2, 在 IsolatedJob 中, 会通过独立的应用程序域 实例一个最终要执行的 Job 的远程对象(通过 RemoteObject).

3, 当中间人的 Execute 方法被调用时, 会调用远程 Job 对象的 Execute 方法.

4, Interrupt 方法同理.

远程对象续约

因为独立的应用程序域用到了远程对象: MarshalByRefObject, 因此涉及到了远程对象的租约过期及续租的问题.

远程对象的租约默认为 5 分钟, 可以重写 InitializeLifetimeService 方法来修改租约的有效期. 但是一个 Job 不确定要执行多长时间, 修改租约有效期不是很合适, 所以这里是通过续约的方式来处理租约过期的问题.

本人对租约了解不多, 不多嘴.感兴趣的话,可参见源码:

QM.RemoteLoader.RemoteObjectSponsor 类

和 QM.RemoteLoader.IsolateDomainLoader类的 GetObject 方法.

立即中断正在执行的任务

这个命题是有条件的, 即: 任务必须实现: IInterruptableJob 接口.

一般一个任务要执行很长时间, 如果不给个中断的接口, 那就只能关闭服务或等任务执行完毕了.

实现了这个接口,在配合 CancellationToken.ThrowIfCancellationRequested 方法就可以中断当前执行的任务了(别告诉我,你的任务是单线程的).

卸载域

任务执行完成后, 会将关联的 IsolatedJob对象释放, 在 IsolatedJob 的 Dispose 方法中,会把IsolateDomainLoader 对象释放,IsolateDomainLoader 释放的时候, 会把关联的子应用程序域卸载.
所以, 如果如果你的任务是多线程的, 请在线程远行完之前, 进行阻塞.

自定义Job的基类

目前, 如果自定义的 Job 的基类在第三方DLL中, 而且第三方DLL未引用到QM.Server 项目中, 并且不在 QM.Server\Jobs 目录下, 会报:

未能加载文件或程序集 XXX 或它的某一个依赖项。系统找不到指定的文件。

解决办法有两种:

1, 将缺少的DLL放到Jobs 目录下.

2, 将缺少的DLL添加引用到 QM.Server 中.

注意, 该限制只针对 Job 的基类. 除基类使用外的第三方DLL不需要这样做, 在JOB上引用就是了.

放上一段不用的, 可终止的 任务示例代码 给你做参考

 

最后, 源码下载

https://github.com/gruan01/QM

Quartz.NET 的任务调度管理工具的更多相关文章

  1. 基于Quqrtz.NET 做的任务调度管理工具

    基于Quqrtz.NET 做的任务调度管理工具 国庆前,需求让我看了一下任务调度的数据表设计.和之前一样,有100多个字段,p1 ~ p100, 我说这是干嘛啊!按这写,写死去了! 然后在网上搜了一下 ...

  2. 使用Quartz.NET进行任务调度管理

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

  3. quartz 定时任务调度管理器

    本项目使用的是spring-quartz 以下配置可以开启多个已知定时任务 <?xml version="1.0" encoding="UTF-8"?&g ...

  4. Docker集群管理工具 - Kubernetes 部署记录 (运维小结)

    一.  Kubernetes 介绍 Kubernetes是一个全新的基于容器技术的分布式架构领先方案, 它是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernete ...

  5. 基于KVM、Xen、OpenVZ等虚拟化技术的WEB在线管理工具

    1.Proxmox proxmox是一个开源的虚拟化管理平台,支持集群管理和HA.在存储方面,proxmox除了支持常用的lvm,nfs,iscsi,还支持集群存储glusterfs和ceph,这也是 ...

  6. Linux服务管理(Ubuntu服务管理工具sysv-rc-conf)(转)

    Linux运行级别 Linux系统任何时候都运行在一个指定的运行级上,并且不同的运行级的程序和服务都不同,所要完成的工作和要达到的目的都不同,系统可以在这些运行级之间进行切换,以完成不同的工作. 运行 ...

  7. RDIFramework.NET框架基于Quartz.Net实现任务调度详解及效果展示

    在上一篇Quartz.Net实现作业定时调度详解,我们通过实例代码详细讲解与演示了基于Quartz.NET开发的详细方法.本篇我们主要讲述基于RDIFramework.NET框架整合Quartz.NE ...

  8. Postman - 功能强大的 API 接口请求调试和管理工具

    Postman 是一款功能强大的的 Chrome 应用,可以便捷的调试接口.前端开发人员在开发或者调试 Web 程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的 Fi ...

  9. JDK 中的证书生成和管理工具 keytool

    参考资料 该文中的内容来源于 Oracle 的官方文档 Java SE Tools Reference .Oracle 在 Java 方面的文档是非常完善的.对 Java 8 感兴趣的朋友,可以直接找 ...

随机推荐

  1. Redis于windows在安装

    下载的windows版本号是redis-2.0.2,解压到D盘下: D:\redis-2.0.2 进到该文件夹下,有下列文件: redis-server.exe:服务程序 redis-check-du ...

  2. VisualStudioOnline协同工作流程

    VisualStudioOnline协同工作流程 项目负责人登陆自己的vsonline新建项目就不多说了. 直接从邀请队友开始 项目负责人操作 被邀请的邮箱必须是微软的邮箱(也就是可以登录visual ...

  3. Jedis连接

    Jedis连接 到场api中的jedis.我们能够发现,jedis类提供了4个构造方法.都可用于连接: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc29 ...

  4. Android供TextView添加多个点击文字

    我们使用社会性软件的过程中会或多或少像别人的帖子点,图. : 能够看到用户页面显示出来的仅仅是点了赞的用户的名称,点击这些名称能够进入到该用户的主页.我们就来实现相似的效果.直接上代码吧. @Over ...

  5. 采用WindowManager添加您自己的自定义视图

    原文地址:使用WindowManager加入自己定义视图 在写手机卫士的时候,用户拨打|接听电话须要显示号码归属地,然后出现了一些异常.在此留下记号,希望对麻友们有帮助: BUG教程 在使用 view ...

  6. C++ STL它vector详细解释

    Vectors    vector它是C++标准模板库部分,它是一种多用途,你可以使用各种数据结构和算法的模板类和库. vector其原因被认为是一个容器.因为它可以被存储为各种类型的对象作为容器.一 ...

  7. 2014年辛星Javascript解读第四节 流程控制语句

    上一节我们介绍了函数,本小节我们介绍一下流程控制语句,对于不论什么一门编程语言来说,流程控制都是很重要的,也就是我们常说的顺序结构.选择结构和循环结构. ************选择结构******* ...

  8. springMVC+angular+bootstrap+mysql的简易购物网站搭建

    springMVC+angular+bootstrap+mysql的简易购物网站搭建 介绍 前端的css框架用了bootstrap, 以及bootstrap的JS组件, 以及很好用的angular(a ...

  9. 一对TCP协议及OSI简介模式

    原文地址:  移步这里

  10. 开始学习java

    .net 许久 看网络java猿飞计划,感觉成了少数类,学校为它,有多难不,有着vb,C,javascript和vs基金会,这并不是说一些语法和框架的熟悉做,搞两天,以一个开发环境,myeclipse ...