`

Quartz.net官方开发指南 第三课:更多关于Jobs和JobDetails

 
阅读更多

如你所见,Job相当容易实现。这里只是介绍有关Jobs本质, IJob接口的Execute(..)方法以及JobDetails中需要理解的内容。 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

在所实现的类成为真正的Job时,期望任务所具有的各种属性需要通知给Quartz。通过JobDetail类可以完成这个工作,这个类在前面的章节中曾简短提及过。现在,我们花一些时间来讨论QuartzJobs的本质和Job实例的生命周期。首先让我们回顾一下第一课中所看到的代码片断:

//definethejobandtieittoourHelloJobclass
JobDetailjob=newJobDetail("job1","group1",typeof(HelloJob));
//Triggerthejobtorunonthenextroundminute
SimpleTriggertrigger=newSimpleTrigger("trigger1","group1",runTime);

//Tellquartztoschedulethejobusingourtrigger
sched.ScheduleJob(job,trigger);

现在考虑如下定义的SimpleJob类:

publicclassSimpleJob:IJob
{

privatestaticILog_log=LogManager.GetLogger(typeof(SimpleJob));

/**////<summary>
///Emptyconstructorforjobinitilization.
///</summary>

publicSimpleJob()
{
}


/**////<summary>
///Calledbythe<seecref="IScheduler"/>whena
///<seecref="Trigger"/>firesthatisassociatedwith
///the<seecref="IJob"/>.
///</summary>

publicvirtualvoidExecute(JobExecutionContextcontext)
{
//Thisjobsimplyprintsoutitsjobnameandthe
//dateandtimethatitisrunning
stringjobName=context.JobDetail.FullName;
_log.Info(
string.Format("SimpleJobsays:{0}executingat{1}",jobName,DateTime.Now.ToString("r")));
}

}

注意,我们给scheduler传入了一个JobDetail实例,而且这个JobDetail实例只是简单提供了类名来引用被执行的Job。每次scheduler执行这个任务时,它就创建这个类的新实例,然后调用该实例的Execute(..)方法。对这种行为的一个推论就是Job类必须有一个无参数的构造函数。另外一个推论就是它使得Job类中定义的成员数据失去意义,因为这些成员数据值在每次执行的时候被清空了。

你可能要问,如何才能为每个Job实例提供属性和配置呢?而且,在执行中如何跟踪Job的状态呢?这些问题的答案是相同的:关键就是JobDataMap,这是JobDetail对象的一部分。

JobDataMap

JobDataMap被用来保存一系列的(序列化的)对象,这些对象在Job执行时可以得到。JobDataMapIDictionary口的一个实现,而且还增加了一些存储和读取主类型数据的便捷方法。

下面是将Job加入到scheduler前使用的一些向JobDataMap加入数据的方法。

//passinitializationparametersintothejob
job1.JobDataMap.Put(ColorJob.FAVORITE_COLOR,"Green");
job1.JobDataMap.Put(ColorJob.EXECUTION_COUNT,
1);

下面的代码展示了在Job执行过程中从JobDataMap 获取数据的代码:

/**////<summary>
///Thisisjustasimplejobthatreceivesparametersand
///maintainsstate
///</summary>
///<author>BillKratzer</author>

publicclassColorJob:IStatefulJob
{

privatestaticILog_log=LogManager.GetLogger(typeof(ColorJob));

//parameternamesspecifictothisjob
publicconststringFAVORITE_COLOR="favoritecolor";
publicconststringEXECUTION_COUNT="count";

//SinceQuartzwillre-instantiateaclasseverytimeit
//getsexecuted,membersnon-staticmembervariablescan
//notbeusedtomaintainstate!
privateint_counter=1;


/**////<summary>
///Calledbythe<seecref="IScheduler"/>whena
///<seecref="Trigger"/>firesthatisassociatedwith
///the<seecref="IJob"/>.
///</summary>

publicvirtualvoidExecute(JobExecutionContextcontext)
{

//Thisjobsimplyprintsoutitsjobnameandthe
//dateandtimethatitisrunning
stringjobName=context.JobDetail.FullName;

//Grabandprintpassedparameters
JobDataMapdata=context.JobDetail.JobDataMap;
stringfavoriteColor=data.GetString(FAVORITE_COLOR);
intcount=data.GetInt(EXECUTION_COUNT);
_log.Info(
string.Format("ColorJob:{0}executingat{1}/nfavoritecoloris{2}/nexecutioncount(fromjobmap)is{3}/nexecutioncount(fromjobmembervariable)is{4}",
jobName,DateTime.Now.ToString(
"r"),favoriteColor,count,_counter));

//incrementthecountandstoreitbackintothe
//jobmapsothatjobstatecanbeproperlymaintained
count++;
data.Put(EXECUTION_COUNT,count);

//Incrementthelocalmembervariable
//Thisservesnorealpurposesincejobstatecannot
//bemaintainedviamembervariables!
_counter++;
}


}

如果使用一个持久的JobStore(在本指南的JobStore章节中讨论),那么必须注意存放在JobDataMap中的内容。因为放入JobDataMap中的内容将被序列化,而且容易出现类型转换问题。很明显,标准.NET类型将是非常安全的,但除此之外的类型,任何时候,只要有人改变了你要序列化其实例的类的定义,就要注意是否打破了程序的兼容性。另外,你可以对JobStoreJobDataMap采用一种使用模式:就是只把主类型和String类型存放在Map中,这样就可以减少后面序列化的问题。

有状态和无状态任务

Triggers也可以有JobDataMaps与之相关联。当scheduler中的Job被多个有规律或者重复触发的Triggers所使用时非常有用。对于每次独立的触发,你可为Job提供不同的输入数据。

Job执行时的JobExecutionContext中取得JobDataMap是惯用手段,它融合了从JobDetail和从Trigger中获的JobDataMap,当有相同名字的键时,它用后者的值覆盖前者值。

StatefulJob——有状态任务

现在,一些关于Job状态数据的附加论题:一个Job实例可以被定义为有状态的或者无状态的无状态的任务只拥有它们被加入到scheduler时所存储的JobDataMap。这意味着,在执行任务过程中任何对Job Data Map所作的更改都将丢失而且任务下次执行时也无法看到。你可能会猜想出,有状态的任务恰好相反,它在任务的每次执行之后重新存储JobDataMap。有状态任务的一个副作用就是它不能并发执行。换句话说,如果任务有状态,那么当触发器在这个任务已经在执行的时候试图触发它,这个触发器就会被阻塞(等待),直到前面的执行完成。

想使任务有状态,它就要实现IStatefulJob接口而不是实现IJob接口。

Job 'Instances' 任务实例

这个课程的最终观点或许已经很明确,可以创建一个单独的Job类,并且通过创建多个JobDetails实例来将它的多个实例存储在scheduler中,这样每个JobDetails对象都有它自己的一套属性和JobDataMap,而且将它们都加入到scheduler中。

当触发器被触发的时候,通过Scheduler中配置的JobFactory来实例化与之关联的Job类。缺省的JobFactory只是简单地对Job类调用GetScheduler ()方法。创建自己JobFactory可以利用应用中诸如Ioc或者DI容器所产生或者初始化的Job实例。

obs的其它属性

这里简短地总结一下通过JobDetail对象可以定义Job的其它属性。

Durability(持久性)-如果一个Job是不持久的, 一旦没有触发器与之关联,它就会被从scheduler 中自动删除。

Volatility(无常性)-如果一个Job是无常的,在重新启动Quartz i scheduler 时它不能被保持。

RequestsRecovery(请求恢复能力) -如果一个Job具备请求恢复能力,当它在执行时遇到scheduler 硬性的关闭(例如:执行的过程崩溃,或者计算机被关机),那么当scheduler重新启动时,这个任务会被重新执行。这种情况下,JobExecutionContext.Recovering 属性将是true

JobListeners(任务监听器) -一个Job如果有0个或者多个JobListeners监听器与之相关联,当这个Job执行时,监听器被会被通知。更多有关JobListeners的讨论见TriggerListeners & JobListeners章节。

JobExecutionException 任务执行异常

最后,需要告诉你一些关于Job.Execute(..)方法的细节。在Execute方法被执行时,仅允许抛出一个JobExecutionException类型异常。因此需要将整个要执行的内容包括在一个'try-catch'块中。应花费一些时间仔细阅读JobExecutionException文档,因为Job能够使用它向scheduler提供各种指示,你也可以知道怎么处理异常。

分享到:
评论

相关推荐

    Quartz 开发指南 中文版

    3. 第三课:更多关于Jobs和JobDetails的内容 4. 第四课:关于Triggers更多的内容 5. 第五课:SimpleTriggers 6. 第六课: CronTriggers 7. 第七课: TriggerListeners和JobListeners 8. 第八课: SchedulerListeners 9. 第...

    Quartz.NET 官方源码及演示例子

    Quartz.NET 官方源码及演示例子,官方下载地址:http://sourceforge.net/projects/quartznet/files/quartznet/

    Quartz.NET 官方源码

    Quartz.NET 官方源码

    Quartz.NET 调度系统 demo

    前言:8月份翻译了Quartz.NET的官方课程:开源的作业调度框架 - Quartz.NET, 有的朋友抱怨难用,确实,目前Qiartz.NET的最新版本还是0.6,还存在很多bug和不完善的地方。本文使用一系列代码示例介绍 Quartz.NET API...

    Quartz.NET-2.0

    Quartz.NET框架的核心是调度器。调度器负责管理Quartz.NET应用运行时环境。Quartz不仅仅是线程和线程管理。为确保可伸缩性,Quartz.NET采用了基于多线程的架构。启动时,框架初始化一套worker线程,这套线程被调度器...

    Quartz.NET-2.1.2官方包

    Quartz.NET-2.1.2 官方包

    ASP.NET使用Quartz.NET实现定时任务调度

    quartz.net+TopShelf

    Quartz最全开发手册(中文版)

    3. 第三课:更多关于Jobs和JobDetails的内容 4. 第四课:关于Triggers更多的内容 5. 第五课:SimpleTriggers 6. 第六课: CronTriggers 7. 第七课: TriggerListeners和JobListeners 8. 第八课: SchedulerListeners 9. 第...

    基于Quartz.Net 的任务调度计划框架

    制定Quartz.NET调度计划,以及监控Quartz.NET以及Topshelf运行情况 应用场景:定时Job配置以及定时Job运行情况记录

    Quartz.net 3.0.7.0数据库持久化.rar

    Quartz.net 任务调度数据库持久化和集群;持久化能保证实例重启后job不丢失、 集群能均衡服务器压力和解决单点问题

    Quartz_net官方开发指南

    Quartz 教程 官方开发指南,非常实用和详细。

    Autofac.Extras.Quartz, Quartz.Net的Autofac集成.zip

    Autofac.Extras.Quartz, Quartz.Net的Autofac集成 Autofac.Extras.Quartz用于 Quartz.Net的Autofac集成包。Autofac.Extras.Quartz 为每个石英作业创建嵌套的litefime作用域。 完成作业执行后释放嵌套作用域。这允许...

    Quartz.net-定时任务 Demo

    Quartz.net-几十分钟后执行代码

    Spring.NET学习笔记25——整合Quartz.NET例子

    刘冬编写Spring.NET学习笔记25——整合Quartz.NET例子。 原文: http://www.cnblogs.com/GoodHelper/archive/2009/11/20/SpringNet_QuartzNet.html

    C# Windows服务 Quartz.Net 代码事例

    C# 使用Quartz.NET作业调度的简单Windows服务事例。

    quartz.net说明文档

    Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中。它提供了巨大的灵 活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。它有很多特征,如:数据库支持,...

    Quartz.NET demo

    Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的...

    Quartz.net定时器

    Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的...

    官方Quartz.NET 2.3.1 源码+15个示例

    官方Quartz.NET 2.3.1 源码(官方2015.1.15更新) 附带15个示例 全部可用

    quartz.net帮助文档

    quartz.net帮助文档 从官网下载的

Global site tag (gtag.js) - Google Analytics