我正在构建一个Windows服务,该服务正在执行计划的任务,该任务使用Quartz.net以固定的时间间隔(每分钟一次)处理(来自旧系统的)命令队列。
如果任务花费的时间超过1分钟,这是不寻常的,但在某些情况下是可能的,那么我希望它简单地忽略它错过触发的触发器。
但是我似乎无法做到这一点。它执行处理,然后快速连续快速触发所有错过的触发器。据我了解,您可以为失火设置一个阈值,但是我似乎无法使它正常工作。
我在作业上使用[DisallowConcurrentExecution()]以确保在任何一次仅运行作业的一个实例。
以下是几个片段。首先传递一些配置信息-这是您设置失火阈值的方式吗?
NameValueCollection config = new NameValueCollection();
config.Add("quartz.jobStore.misfireThreshold", "600000");
schedFact = new StdSchedulerFactory(config);
使用我认为是正确的忽略失火设置来构建触发器:
var trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule( x => x.WithMisfireHandlingInstructionIgnoreMisfires()
.WithIntervalInSeconds(60)
.RepeatForever())
.Build();
思想大加赞赏。
工作代码:
此时,您只需要考虑一些粗略的想法,就可以在控制台应用程序中运行该应用程序,并随机延迟一项工作,因此它会在为此设置的10秒间隔内进行拍摄。经过几次延误后,所有备份的失火都迅速相继触发。
[DisallowConcurrentExecution()]
public class SomeJob : IJob
{
public SomeJob() { }
public void Execute(IJobExecutionContext context)
{
Random rnd = new Random(DateTime.UtcNow.Second);
int delay = rnd.Next(2);
Console.WriteLine("Executing Job with delay of "+ delay + " at " + DateTime.UtcNow.ToString());
if (delay == 1)
{
System.Threading.Thread.Sleep(1000 * 25); // sleep for 25 seconds
}
}
}
Example console output:
Executing Job with delay of 1 at 21/05/2015 21:27:17
Executing Job with delay of 1 at 21/05/2015 21:27:42
Executing Job with delay of 0 at 21/05/2015 21:28:07 <-- stacked misfires
Executing Job with delay of 0 at 21/05/2015 21:28:07 <--
Executing Job with delay of 0 at 21/05/2015 21:28:07 <--
Executing Job with delay of 0 at 21/05/2015 21:28:07 <--
Executing Job with delay of 0 at 21/05/2015 21:28:16
Executing Job with delay of 0 at 21/05/2015 21:28:26
Executing Job with delay of 1 at 21/05/2015 21:28:36
Executing Job with delay of 0 at 21/05/2015 21:29:01
Executing Job with delay of 0 at 21/05/2015 21:29:01
Executing Job with delay of 1 at 21/05/2015 21:29:06
最佳答案
WithMisfireHandlingInstructionIgnoreMisfires()
是您所需的错误方法,这并不意味着作业不会触发失火,而是意味着它将尽快触发所有错过的触发器,然后将其恢复为常规时间表。您所看到的正在发生。
您需要的是WithMisfireHandlingInstructionNextWithRemainingCount()
。这将通知调度程序忽略失火并等待下一个调度时间。
错误处理的策略可能会有些困惑,有关简洁的说明,请看here(它用于Java调度程序,但这并不重要)。
即使采用正确的策略,您也需要了解失火阈值的工作原理-如果弄错了阈值,则失火的触发器仍可能会触发。
从文档中:“失火是触发器必须错过其下一次触发时间才能将其视为“未触发”并因此应用其失火指令的时间跨度”。
您已将值设置为600000
毫秒(并且此值适用于所有触发器,不幸的是每个触发器没有阈值)-失火策略仅在触发器应在触发时间后触发600000
毫秒的情况下才会应用。您可以根据需要降低或增加它。
有关失火阈值的更多信息,请阅读here。