我已经提到了以下问题,但没有帮助我解决问题。
在 Quartz.NET 中,有没有一种方法可以设置一个只允许一个 Job 实例运行的属性?
https://github.com/quartznet/quartznet/issues/469
对于 CronTrigger,在调度程序中使用了以下内容cs.WithMisfireHandlingInstructionDoNothing()。
在HelloJob
DisallowConcurrentExecution.
代码怎么了?
在 Execute 方法中,我已经设置了断点。根据我的代码,execute 方法将在每个 10 秒内执行。
打到第一个断点后,又等了31秒。然后我删除了断点并执行了代码,根据我的期望,应该只执行一次以进行另一次尝试。
但是 execute 方法在另外 10 秒内执行了 3 次(3*10 秒)。
如何解决这个问题?
调度程序代码。
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);
Run Code Online (Sandbox Code Playgroud)
作业执行代码。
[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);
}
}
Run Code Online (Sandbox Code Playgroud)
================================================== ==================
无需进行互锁或手动管理。
Quartz 已经被设计成只完成第一个时间表,下一个开始。
所以我们不用担心它会并发运行。
例如(像我这样的人:-p),调度程序安排了 10 分钟。
但是如果我们在execute方法中复制下面的代码,可以看到,第一次,需要20分钟才能完成。第二次,需要 15 分钟才能完成。
10 分钟后不会有下一个时间表开始。
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++;
Run Code Online (Sandbox Code Playgroud)
在您的情况下发生的情况是,在作业的第一个长 30 秒执行期间Quartz安排了其他三个执行。这就是为什么在长时间执行之后看到三个短执行。它们不是同时执行的。一个接一个,但没有延迟。这是怎么Quartz设计。
[DisallowConcurrentExecution]
public class HelloJob : IJob
{
public static int count = 1;
public void Execute(IJobExecutionContext context)
{
Console.WriteLine("HelloJob strted On." + DateTime.UtcNow.Ticks);
if (count == 1)
Thread.Sleep(TimeSpan.FromSeconds(30));
Interlocked.Increment(ref count);
}
}
Run Code Online (Sandbox Code Playgroud)
和输出:
Ctrl+C to exit.
HelloJob strted On.636280218500144776
HelloJob strted On.636280218800201691
HelloJob strted On.636280218800211705
HelloJob strted On.636280218800222083
HelloJob strted On.636280218900009629
HelloJob strted On.636280219000000490
Run Code Online (Sandbox Code Playgroud)
看,时间戳是不同的,next 在 first 完成后开始。
如果您想避免这种行为,您应该增加作业之间的延迟,或者按照@BrunoFerreira 的建议手动处理此作业的时间表。