在 Quartz.net 中,一次运行一个作业实例

Jee*_*Jsb 3 c# quartz.net

我已经提到了以下问题,但没有帮助我解决问题。

在 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)

And*_*nov 5

在您的情况下发生的情况是,在作业的第一个长 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 的建议手动处理此作业的时间表。