在上一篇中介绍了简单的利用Quartz执行定时任务
这一次介绍Quartz传递参数
比如 执行的任务中,传给指定人的时候需要带一些特定的参数,例如个人的姓名等。
方法一、声明作业的时候携带参数
IJobDetail job=JobBuilder.Create<SendMessageJob>() .WithIdentity("sendMessageJob", "group1") //分组 .WithDescription("this is message job") //作业描述 .Build(); //传递参数 job.JobDataMap.Add("Student", "张三"); job.JobDataMap.Add("Year", DateTime.Now.Year);
任务方法中:
string stu1 = context.JobDetail.JobDataMap.GetString("Student");
方法二、在声明策略时携带参数
ITrigger trigger=TriggerBuilder.Create() .WithIdentity("sendMessageJob", "group1") //分组 // .StartNow() //马上执行一次 .WithSimpleSchedule(w => w.WithIntervalInSeconds(5).WithRepeatCount(3)) //没5秒重复一次。最多重复4次 .Build(); trigger.JobDataMap.Add("Year", DateTime.Now.Year+1);
任务方法中读取:
int year = context.Trigger.JobDataMap.GetInt("Year");
方法三、使用MergedJobDataMap
需要在策略或者作业中声明好参数
然后在任务方法中读取:
int year2 = context.MergedJobDataMap.GetInt("Year");
需要注意的是这个方法会覆盖参数,也就是假如trigger和JobDetail声明同名参数的时候,他会默认取后面的值。
比如上面两个方法都声明了Year,用此方法的话他会取下面的值,也就是DateTime.Now.Year+1。
假如想让上一次执行的结果作为下一次执行的参数??
在我们声明的SendMessageJob里,它继承于IJob,当它每次执行的时候都会重新调用构造函数,重新拉值,也就是说它本身是一个无状态的类。
那么想让上一次的值保留,就必须要他持久化。
那么可以在SendMessageJob这个类上面声明[PersistJobDataAfterExecution]。它表示每次执行后都会持久化数据
[PersistJobDataAfterExecution] public class SendMessageJob : IJob
我声明的Year参数
int year = context.JobDetail.JobDataMap.GetInt("Year");
在任务的结尾加上
context.JobDetail.JobDataMap.Put("Year", year + 1);
也就是下次获取的Year值是这一次的加1
实际结果发现,后几次不再获取JobDetail声明的当前年,而是依次在前一年基础上加1年
但是有问题就是加入我任务执行的时间间隔超过了我重复的时间间隔。比如原定于每3秒重复一次,结果任务便执行了5秒。
实践后发现,后一次的结果并非都和预想的一样。比如上面实例,按道理来说应该是每次年份加1,我让任务休眠5秒,使得后一次的结果获取不到前面的值导致错乱。
这种情况下,需要保证任务每次都执行完毕再开始下一次任务。并不是强制按照声明的策略,而是看任务完毕与否。
可以在SendMessageJob上声明[DisallowConcurrentExecution]。
它表示不允许当前执行,必须等上一次任务执行完才可以
使用这个标签之后,年份得到了正确的值。时间间隔也并非按照声明的每3秒,而是换成了5秒。