在Quartz.NET中有没有办法设置一个只允许一个Job实例运行的属性?

Mar*_*ark 33 .net quartz.net

我有一个每X分钟运行一次的服务.如果由于某些不可预见的原因,该作业的耗时超过X分钟,我想确保触发器不会启动此作业的第二个实例.

示例场景

  • 我有Job X,拿起文件,每隔1分钟由Quartz触发.
  • 作业X通常可以在1分钟内处理100个文件,超过100个文件的任何时间都需要超过1分钟.
  • 自上次运行时起,150个文件恰好在那里,因此Job X启动并开始处理.当达到1分钟时,处理了100个文件,剩下50个文件,并且作业X继续运行.
  • 然而,Job X的第二个实例被启动,因为触发器每1分钟触发一次.
  • 我现在有2个Job X实例获取相同的50个文件.

有没有办法连接Quartz.NET只允许1个Job的实例?我可以用第二个触发器等待第一个触发完成,或者我也可以选择跳过第二个触发器,因为它会在一分钟内再次触发.



我看了一下Quartz API的Java版本,发现了一个属性' DisallowConcurrentExecution ',但是在.NET版本中找不到类似的东西.

我的Quartz.NET实现代码

public IScheduler Scheduler { get; set; }
public IJobListener AutofacJobListener { get; set; }

public void Start()
{
var trigger = TriggerUtils.MakeMinutelyTrigger(1);
trigger.Name = @"Document Import Trigger";

Scheduler.ScheduleJob(new JobDetail("Document Import", null, typeof(DocumentImportJob)), trigger);
Scheduler.AddGlobalJobListener(AutofacJobListener);
Scheduler.Start();
}

Kei*_*ows 51

使用DisallowConcurrentExecution属性.

按如下方式声明您的类:

[DisallowConcurrentExecution]
public class SomeTask : IJob
{

} 
Run Code Online (Sandbox Code Playgroud)

失火

"失火说明"触发器的另一个重要特性是它的"失火指令".如果由于调度程序被关闭而导致持续触发"错过"其触发时间,或者因为Quartz.NET的线程池中没有可用的线程,则会发生失败不同的触发器类型可以使用不同的失火指令.默认情况下,它们使用"智能策略"指令 - 它具有基于触发器类型和配置的动态行为.当调度程序启动时,它会搜索任何持久触发器失误,然后根据他们单独配置的失火指令更新它们.当你在自己的项目中开始使用Quartz.NET时,你应该熟悉在给定触发器类型上定义的失火指令,并解释在他们的API文档中.有关失火指令的更多具体信息将在每个触发器特定的教程课程中给出 类型."

查看这些页面底部的"触发失火说明"信息:

第5课:SimpleTrigger

第6课:CronTrigger

旧的Quartz.NET API答案:

http://quartznet.sourceforge.net/apidoc/topic142.html:

IStatefulJob实例遵循与常规IJob实例略有不同的规则.关键的区别在于,每次执行作业后都会重新保存关联的JobDataMap,从而保留下次执行的状态.另一个区别是有状态作业不允许同时执行,这意味着在IJob.Execute方法完成之前发生的新触发器将被延迟.

因此,请按如下方式声明"Job"类:

class DocumentImportJob : IStatefulJob
{
   ......
} 
Run Code Online (Sandbox Code Playgroud)

为避免延迟任务在作业完成后立即重新启动(当作业超过1分钟并导致触发'失火'时),请在创建触发器时执行以下操作(根据使用的触发器类型进行调整):

myJobTrigger.MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing;  
Run Code Online (Sandbox Code Playgroud)

https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/more-about-triggers.html

  • IStatefulJob 已弃用。而是使用 Job 类定义上方的 [DisallowConcurrentExecution]。这是根据 Quartz.NET 2.2.1 的。失火可以通过以下与触发器初始化一起使用的方法来处理:WithMisfireHandlingInstructionIgnoreMisfires() (2认同)

Bit*_*der 45

作为对此答案的更新,在较新版本的Quartz.Net中,现在通过您应用于作业实现的属性"DisallowConcurrentExecution"来完成:

[DisallowConcurrentExecution]
public class MyJob : IJob  
{
    ..
}
Run Code Online (Sandbox Code Playgroud)

对于失火指令,以下是如何做到这一点:

var trigger = TriggerBuilder.Create()
    .WithSimpleSchedule(ssb => ssb.WithIntervalInMinutes(interval)
        .RepeatForever()
        .WithMisfireHandlingInstructionIgnoreMisfires()
    )
    .Build();
Run Code Online (Sandbox Code Playgroud)