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

时间:2011-05-12 20:42:43

标签: .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();
}

4 个答案:

答案 0 :(得分:50)

使用DisallowConcurrentExecution属性。

按如下方式声明您的课程:

[DisallowConcurrentExecution]
public class SomeTask : IJob
{

} 

<强>失火

  

“失火说明”触发器的另一个重要特性是它   “失火指令”。如果持续触发,则会发生失火   由于调度程序被关闭,“错过”其启动时间,或   因为Quartz.NET的线程池中没有可用的线程   执行工作。不同的触发类型有不同的失火   他们可以获得的指示。默认情况下,他们使用“智能政策”   指令 - 具有基于触发类型和动态行为的动态行为   组态。当调度程序启动时,它会搜索任何调度程序   持有失败的持久性触发器,然后更新每个触发器   它们基于各自配置的失火指令。什么时候   你开始在你自己的项目中使用Quartz.NET   你自己熟悉定义的失火指令   给定的触发器类型,并在其API文档中进行了解释。   将提供有关失火指令的更多具体信息   在每个触发器类型特定的教程课程中。“

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

Lesson 5: SimpleTrigger

Lesson 6: CronTrigger

旧的Quartz.NET API回答:

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

  

IStatefulJob 实例遵循与常规规则略有不同的规则   IJob实例。关键的区别是   他们关联的JobDataMap是   每次执行后都会重新坚持下去   这项工作,因此保留了国家   下次执行。另一个区别   是有条不紊的工作是不允许的   同时执行,这意味着   在之前发生的新触发器   完成IJob.Execute方法   将被推迟。

所以,按如下方式声明你的'Job'类:

class DocumentImportJob : IStatefulJob
{
   ......
} 

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

myJobTrigger.MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing;  

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

答案 1 :(得分:44)

作为对此答案的更新,在较新版本的Quartz.Net中,现在通过属性&#34; DisallowConcurrentExecution&#34;你申请工作:

[DisallowConcurrentExecution]
public class MyJob : IJob  
{
    ..
}

对于失火指令,这是如何做到的:

var trigger = TriggerBuilder.Create()
    .WithSimpleSchedule(ssb => ssb.WithIntervalInMinutes(interval)
        .RepeatForever()
        .WithMisfireHandlingInstructionIgnoreMisfires()
    )
    .Build();

答案 2 :(得分:4)

嗯,一个简单的方法是将标志值存储在某处的变量中,并在进入作业方法时检查变量。

这样你就可以让工作第二次“开始”,它会在没有做任何实际工作的情况下立即退出。

以下是一个例子:

private volatile bool _IsRunning;

...

if (Interlocked.Exchange(ref _IsRunning, true))
    return;
try
{
    // job code
}
finally
{
    _IsRunning = false;
}

答案 3 :(得分:-5)

public bool Validar(IJobExecutionContext context)         {

        if (context.Scheduler.GetCurrentlyExecutingJobs().Any(x => x.FireInstanceId != context.FireInstanceId
         && x.JobDetail.Key == context.JobDetail.Key))
        {
            return true;
        }
        else
        {
            return false;
        }

    }