我提到了以下问题,但没有帮助我解决问题。
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
对于CronTrigger,在调度程序cs.WithMisfireHandlingInstructionDoNothing()
中使用以下内容。
在HelloJob
中应用以下属性
DisallowConcurrentExecution
。
代码怎么了?
在Execute方法中,我设置了断点。根据我的代码,execute方法将在10秒内执行。
在达到第一个破发点之后,我又等了31秒。然后我根据我的期望删除了断点并执行了代码,该代码应该只执行一次以进行另一次尝试。
但执行方法在另一个内执行了3次(3 * 10秒) 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);
工作执行代码。
[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);
}
}
=============================================== =====================
无需进行联锁或手动管理。
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++;
答案 0 :(得分:2)
在你的情况下发生的事情是,在第一个长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);
}
}
输出:
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
请参阅,时间戳不同,接下来在第一次完成后开始。
如果你想避免这种行为,你应该增加工作之间的延迟,或者@BrunoFerreira建议手动处理这个工作的时间表。
答案 1 :(得分:1)
我几天前遇到过同样的问题。结果我不得不安排工作和它的触发器。 我申请结束时,我正在使用这种方法。
private void StopAllJobs()
{
// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();
// get a scheduler, start the schedular before triggers or anything else
sched = schedFact.GetScheduler();
var executingJobs = sched.GetCurrentlyExecutingJobs();
foreach (var job in executingJobs)
{
sched.Interrupt(job.JobDetail.Key);
sched.UnscheduleJob(job.Trigger.Key);
sched.DeleteJob(job.JobDetail.Key);
}
sched.Clear();
}
希望这会对你有所帮助。
答案 2 :(得分:0)
只需使用这样的东西:
private static readonly SemaphoreSlim Lock = new SemaphoreSlim(1, 1);
if (await Lock.WaitAsync(new TimeSpan(0, 0, 30)))
{
...
}
我们有一些工作,而且效果很好。