在 Quartz.net、运行 中一次一个作业实例
In Quartz.net, run one instance of a job at a time
我提到了以下问题,但没有帮助我解决问题。
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 方法中,我设置了断点。根据我的代码,每个执行方法将在 10 秒内执行。
打到第一个破发点后,我又等了31秒。然后我删除了断点并执行了代码,根据我的预期,应该只执行一次以进行另一次尝试。
But the execute method executed 3 times (3*10 seconds) within another
10 seconds.
如何解决?
调度程序代码。
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++;
几天前我遇到了同样的问题。结果是我不得不取消工作安排,这是触发。
我正在使用此方法在我的应用程序结束时执行此操作。
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();
}
希望对您有所帮助。
你的情况是,在第一个长达 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 的建议手动处理此作业的计划。
只需使用这样的东西:
private static readonly SemaphoreSlim Lock = new SemaphoreSlim(1, 1);
if (await Lock.WaitAsync(new TimeSpan(0, 0, 30)))
{
...
}
我们有几份工作,这很好用。
我提到了以下问题,但没有帮助我解决问题。
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 方法中,我设置了断点。根据我的代码,每个执行方法将在 10 秒内执行。
打到第一个破发点后,我又等了31秒。然后我删除了断点并执行了代码,根据我的预期,应该只执行一次以进行另一次尝试。
But the execute method executed 3 times (3*10 seconds) within another 10 seconds.
如何解决?
调度程序代码。
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++;
几天前我遇到了同样的问题。结果是我不得不取消工作安排,这是触发。 我正在使用此方法在我的应用程序结束时执行此操作。
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();
}
希望对您有所帮助。
你的情况是,在第一个长达 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 的建议手动处理此作业的计划。
只需使用这样的东西:
private static readonly SemaphoreSlim Lock = new SemaphoreSlim(1, 1);
if (await Lock.WaitAsync(new TimeSpan(0, 0, 30)))
{
...
}
我们有几份工作,这很好用。