簡體   English   中英

在 Quartz.net 中,一次運行一個作業實例

[英]In Quartz.net, run one instance of a job at a time

我已經提到了以下問題,但沒有幫助我解決問題。

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

作業執行代碼。

[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++;

在您的情況下發生的情況是,在作業Quartz第一個長 30 秒執行期間安排了其他三個執行。 這就是為什么在長時間執行之后看到三個短執行。 它們不是同時執行的。 一個接一個,但沒有延遲。 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

看,時間戳是不同的,next 在 first 完成后開始。

如果您想避免這種行為,您應該增加作業之間的延遲,或者按照@BrunoFerreira 的建議手動處理此作業的時間表。

幾天前我遇到了同樣的問題。 結果我不得不取消工作安排,這是觸發器。 當我的應用程序結束時,我正在使用此方法來執行此操作。

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();
}

希望這對你有幫助。

只需使用這樣的東西:

        private static readonly SemaphoreSlim Lock = new SemaphoreSlim(1, 1);

        if (await Lock.WaitAsync(new TimeSpan(0, 0, 30)))
        {
           ...
        }

我們有一些工作,這很好用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM