Job和JobDetails的关系
接一篇的例子
ISchedulerFactory schedFact = new StdSchedulerFactory(); IScheduler sched = schedFact.GetScheduler(); sched.Start(); IJobDetail job = JobBuilder.Create<FirstJob>() .WithIdentity("myJob", "group1") .Build(); ITrigger trigger = TriggerBuilder.Create() .WithIdentity("myTrigger", "group1") .StartNow() .Build(); sched.ScheduleJob(job, trigger);
Job和JobDetails是任务相关2个对象,所有的Job都实现了IJob接口,所有的JobDetails都实现了IJobDetails接口。
Quartz.NET中,我们使用调用器Scheduler, 将一个JobDetails对象关联到一个触发器中,而非直接关联一个Job对象到触发器对象中。原因是Job只是定义任务需要做什么,而不包含任务执行时需要的运行环境, 如果一个Job和具体的运行环境绑定,就没有办法复用了。
JobDetails包含了Job的所有运行环境,上面的实例代码中,我们使用JobBuilder类,来根据指定的Job类型,生成了一个对应的JobDetails。在JobDetails关联到触发器之后,触发器触发,JobDetails对象会自动进行以下操作
- 根据定义实例化一个对应的Job对象
- 为Job对象准备运行环境
- 执行Job对象的Execute方法
Job的运行环境
JobDetails如何为Job指定运行环境呢?
查看IJobDetails接口的定义,我们可以看到一个名为JobDataMap的对象,这个对象会在Job实例化成功之后,填充具体的运行环境。
下面我们修改一下我们当前的代码,首先修改一下program.cs
ISchedulerFactory schedFact = new StdSchedulerFactory(); IScheduler sched = schedFact.GetScheduler(); sched.Start(); IJobDetail job = JobBuilder.Create<FirstJob>() .UsingJobData("MyName", "Lunan") .WithIdentity("myJob", "group1") .Build(); ITrigger trigger = TriggerBuilder.Create() .WithIdentity("myTrigger", "group1") .StartNow() .Build(); sched.ScheduleJob(job, trigger);
这里UsingJobData方法,会将录入的键值对,保存在JobDataMap中,Job运行的时候,可以从上下文对象中获取到这些添加的键值对。
在这里调用多次UsingJobData方法可以录入多个键值对。
下面我们继续修改一下FirstJob类, 我们希望任务执行的时候,将MyName变量输出到控制台
public class FirstJob : IJob { public void Execute(IJobExecutionContext context) { JobDataMap dataMap = context.JobDetail.JobDataMap; Console.WriteLine($"Hello {dataMap.GetString("MyName")}"); Console.WriteLine("Hello World."); } }
这里从运行上下文对象context可以从读取JobDataMap中定义的参数。
查看效果
我们重新运行程序,程序正确读出了参数MyName
使用注入的方式接收参数
Quartz.Net支持注入的方式传递参数,这里我们对上面的Job代码进行一下微小的调整,添加一个名为MyName的属性,提供get;set;方法,直接使用该属性在控制台输出字符串,也可以得到一样的效果,而且代码看起来更加简洁
public string MyName { get; set; } public void Execute(IJobExecutionContext context) { Console.WriteLine($"Hello {MyName}"); Console.WriteLine("Hello World."); }