Quartz.NET 架构与源代码分析系列 part 2 :Job 作业
在上一篇Quartz.NET 架构与源代码分析系列 part 1 :Quartz.NET 入门我们介绍了Quartz.NET 的基本知识和简单的应用,可以看出来它的使用是非常简单的,只要短短的几行代码就可以在自己的应用程序嵌入强大的作业调度功能。图1是调度器的原理示意图。
图1 调度器的原理示意图
从图1可以看出,作业流程是在调度器的统一调度下完成的,它可以调度多个作业,触发器提供作业执行的条件(每天 8:00 am),触发器与作业关联,它们是 1:N 的关系,1个触发器可以关联1个或多个作业。
附带的作业
我们知道要实现自己的作业功能只要继承 IJob 接口并实现 Execute(JobExecutionContext context) 方法,再把它添加到调度器,调度器会调用执行Execute(JobExecutionContext context) 方法。调用期间,调度器会跟踪作业和它们的执行次数。Quartz.NET 默认提供了 FileScanJob 监视某个文件是否被修改,NativeJob 执行指定程序,NoOpJob 空操作用来给系统调用 ITriggerListener 、IJobListener ,以及 SendMailJob 邮件发送作业。
作业执行上下文
作业执行上下文由 JobExecutionContext 类实现,它的类图如图2所示。
它有一个存储作业执行时数据的重要属性:MergedJobDataMap,它是 JobDataMap 类型,也可以使用 JobExecutionContext.JobDetail.JobDataMap 来获得 JobDataMap 对象的引用。作为传递参数的容器,JobDataMap 间接继承了 DirtyFlagMap,DirtyFlagMap 内嵌了 Hashtable 容器,它有一组数据读写方法。可以使用 Visual Studio 的类图来查看。
有状态与无状态的作业
以上我们的作业实例都是从 IJob 继承,Quartz.NET 里还有 IStatefulJob 、IInterruptableJob,它的声明方式为:
IInterruptableJob 接口提供了一个中断方法,但是 IStatefulJob 没有自己的方法。从 Quartz.NET 官方了解到:
一个 Job 实例可以被定义为“有状态的”或者“无状态的”。在执行无状态的任务过程中任何对 JobDataMap 所作的更改都将丢失。有状态的任务恰好相反,它在任务的每次执行之后重新存储 JobDataMap 。有状态任务的一个缺点就是它不能并发执行。也就是说,如果任务有状态,那么当触发器试图触发它,触发器就会被阻塞直到前面的执行完成。想使任务有状态,它就要实现 IStatefulJob 接口而不是实现IJob接口。
从上面可以知道 IStatefulJob 应该有管理 JobDataMap 的方法,但这个接口在 Quartz.NET 1.0 版本还没有实现。预计在以后的版本应该会加强这个功能的。
示例效果
图4 Quartz.NET 示例图
该示例还不够完善,所以源代码没有传上来,计划在下一篇就共享出来。
下一篇文章我们将进入第3 部分:Trigger 触发器
参考文章
1.The Official Quartz.NET Tutorial
2.Quartz.net官方开发指南 第三课:更多关于Jobs和JobDetails