I have referred the following question but didn't help me to solve the issue.
In Quartz.NET is there a way to set a property that will only allow one instance of a Job to run?
https://github.com/quartznet/quartznet/issues/469
For CronTrigger, Used the following in the scheduler cs.WithMisfireHandlingInstructionDoNothing()
.
Applied the following attribute in the HelloJob
DisallowConcurrentExecution
.
What happened with the code?
In the Execute method, I have set the breaking point. Based on my code the execute method will execute in 10 seconds each.
After hitting the first breaking point, I have waited for another 31 seconds. Then I have removed the breaking point and executed the code, based on my expectation, that should be execute only one time for another attempt.
But the execute method executed 3 times (3*10 seconds) within another 10 seconds.
How to solve this?
Scheduler code.
ISchedulerFactory schedFact = new StdSchedulerFactory();
IScheduler sched = schedFact.GetScheduler();
sched.Start();
// define the job and tie it to our HelloJob class
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("myJob", "group1")
.Build();
// Trigger the job to run now, and then every 40 seconds
ITrigger trigger = trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithCronSchedule("0/10 * * * * ?",cs=>cs.WithMisfireHandlingInstructionDoNothing())
.ForJob("myJob", "group1")
.Build();
TriggerKey key = new TriggerKey("trigger3", "group1");
sched.ScheduleJob(job, trigger);
Job execution code.
[DisallowConcurrentExecution]
public class HelloJob : IJob
{
public static int count = 1;
public void Execute(IJobExecutionContext context)
{
Console.WriteLine(count+" HelloJob strted On." + DateTime.Now.ToString());
if (count == 1)
Thread.Sleep(TimeSpan.FromSeconds(30));
Interlocked.Increment(ref count);
}
}
====================================================================
Solution
No need to go for interlocked or manual management.
Quartz is already designed like only finishes the first schedule, the next one starts.
So we no need to worry about that it will run concurrently.
For example (The people like me :-p), the scheduler scheduled for 10 mins.
But if we copy the following code in the execute method, you can see that, On the first time, it will take 20 minutes to finish. On the second time, it will take 15 minutes to finish.
In between there won't be next schedule starts after 10 mins over.
var startTime = DateTime.UtcNow;
if (count == 1)
{
while (DateTime.UtcNow - startTime < TimeSpan.FromSeconds(20))
{
// Execute your loop here...
}
}
else if (count > 1)
{
while (DateTime.UtcNow - startTime < TimeSpan.FromSeconds(15))
{
// Execute your loop here...
}
}
count++;