In Quartz.NET is there a way to set a property that will only allow one instance of a Job to run?

别来无恙 提交于 2019-11-29 23:44:09
Keith Blows

Use the DisallowConcurrentExecution attribute.

Declare your class as follows:

[DisallowConcurrentExecution]
public class SomeTask : IJob
{

} 

Misfires

"Misfire Instructions Another important property of a Trigger is its "misfire instruction". A misfire occurs if a persistent trigger "misses" its firing time because of the scheduler being shutdown, or because there are no available threads in Quartz.NET's thread pool for executing the job. The different trigger types have different misfire instructions available to them. By default they use a 'smart policy' instruction - which has dynamic behavior based on trigger type and configuration. When the scheduler starts, it searches for any persistent triggers that have misfired, and it then updates each of them based on their individually configured misfire instructions. When you start using Quartz.NET in your own projects, you should make yourself familiar with the misfire instructions that are defined on the given trigger types, and explained in their API documentation. More specific information about misfire instructions will be given within the tutorial lessons specific to each trigger type."

Check out the "trigger misfire instructions" information at the bottom of these pages:

Lesson 5: SimpleTrigger

Lesson 6: CronTrigger

Old Quartz.NET API answer:

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

IStatefulJob instances follow slightly different rules from regular IJob instances. The key difference is that their associated JobDataMap is re-persisted after every execution of the job, thus preserving state for the next execution. The other difference is that stateful jobs are not allowed to Execute concurrently, which means new triggers that occur before the completion of the IJob.Execute method will be delayed.

So, declare your 'Job' class as follows:

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

To avoid delayed tasks re-firing immediately after job completes (when the job takes more than 1 minute and causes a trigger 'misfire'), do the following when creating your trigger(s) (adjust depending on the trigger type used):

myJobTrigger.MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing;  

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

Bittercoder

As an update to this answer, in newer versions of Quartz.Net this is now done via an attribute "DisallowConcurrentExecution" you apply to your job implementation:

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

And for the misfire instruction, here is how to do that:

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

Well, one simple way to do it would be to just store a flag value in a variable somewhere, and check the variable upon entrance to the job method.

That way you would just let the job "start" a second time, it would just exit immediately without doing any real work.

Here's an example:

private volatile bool _IsRunning;

...

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

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;
        }

    }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!