簡體   English   中英

在 Quartz.Net 中調度相關作業

[英]Scheduling Dependent Jobs in Quartz.Net

我需要一些幫助。 我試圖弄清楚如何在 Quartz.Net 中安排作業。 Quartz 中的作業對應於我的 Web 應用程序中的任務,它們都是我的 Web 應用程序中的作業的一部分。 我希望用戶能夠按需啟動作業(WebApplication 上下文)並使其立即運行或安排將來的作業,並且可能在給定的時間間隔內重復。 我知道所有這些項目是如何在 Quartz 中單獨完成的,但我很難把它們放在一起。

例如,在我的 web 應用程序中,我的工作可能有多個任務,按特定順序。 我希望能夠在石英中安排這些任務,以便它們按照我的 Web 應用程序中確定的順序執行。 有人知道如何做到這一點嗎? 我已經閱讀了 Quartz 文檔,說要在 JobDataMap 中存儲下一個 Job,只是在努力解決它。

我目前正在等待創建 Quartz 作業,直到用戶請求安排作業或運行它。 您是否認為我應該在 Web 應用程序中創建作業並觸發創建任務,然后從任務 object 中提取該信息以在 Quartz 中進行調度?

您需要的是JobChainingJobListener class,它可以幫助您按照您想要的特定順序為您的作業創建一個執行鏈。

using System;
using System.Text;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.Calendar;
using Quartz.Listener;
using Quartz.Impl.Matchers;
using System.Threading;

namespace QuartzNET.Samples
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create RAMJobStore instance
            DirectSchedulerFactory.Instance.CreateVolatileScheduler(5);
            ISchedulerFactory factory = DirectSchedulerFactory.Instance;

            // Get scheduler and add object
            IScheduler scheduler = factory.GetScheduler();          

            StringBuilder history = new StringBuilder("Runtime History: ");
            scheduler.Context.Add("History", history);

            JobKey firstJobKey = JobKey.Create("FirstJob", "Pipeline");
            JobKey secondJobKey = JobKey.Create("SecondJob", "Pipeline");
            JobKey thirdJobKey = JobKey.Create("ThirdJob", "Pipeline"); 

            // Create job and trigger
            IJobDetail firstJob = JobBuilder.Create<FirstJob>()
                                       .WithIdentity(firstJobKey)
                                       //.StoreDurably(true)
                                       .Build();

            IJobDetail secondJob = JobBuilder.Create<SecondJob>()
                                       .WithIdentity(secondJobKey)                                       
                                       .StoreDurably(true)                                       
                                       .Build();

            IJobDetail thirdJob = JobBuilder.Create<ThirdJob>() 
                                       .WithIdentity(thirdJobKey)
                                       .StoreDurably(true)
                                       .Build();

            ITrigger firstJobTrigger = TriggerBuilder.Create()
                                             .WithIdentity("Trigger", "Pipeline")
                                             .WithSimpleSchedule(x => x
                                                 .WithMisfireHandlingInstructionFireNow()
                                                .WithIntervalInSeconds(5)    
                                                .RepeatForever())
                                             .Build();

            JobChainingJobListener listener = new JobChainingJobListener("Pipeline Chain");
            listener.AddJobChainLink(firstJobKey, secondJobKey);
            listener.AddJobChainLink(secondJobKey, thirdJobKey);            

            scheduler.ListenerManager.AddJobListener(listener, GroupMatcher<JobKey>.GroupEquals("Pipeline"));

            // Run it all in chain
            scheduler.Start();
            scheduler.ScheduleJob(firstJob, firstJobTrigger);
            scheduler.AddJob(secondJob, false, true);
            scheduler.AddJob(thirdJob, false, true);

            Console.ReadLine();
            scheduler.Shutdown();
            Console.WriteLine("Scheduler shutdown.");
            Console.WriteLine(history);
            Console.ReadLine();
        }
    }

    class FirstJob : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            var history = context.Scheduler.Context["History"] as StringBuilder;
            history.AppendLine();
            history.AppendFormat("First {0}", DateTime.Now);            
            Console.WriteLine("First {0}", DateTime.Now);
        }
    }

    class SecondJob : IJob 
    {
        public void Execute(IJobExecutionContext context)
        {
            var history = context.Scheduler.Context["History"] as StringBuilder;
            history.AppendLine();
            history.AppendFormat("Second {0}", DateTime.Now);
            Console.WriteLine("Second {0}", DateTime.Now);            
        }
    }

    class ThirdJob : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            var history = context.Scheduler.Context["History"] as StringBuilder;
            history.AppendLine();
            history.AppendFormat("Third {0}", DateTime.Now);
            Console.WriteLine("Third {0}", DateTime.Now);
            Console.WriteLine();
        }
    }
}

關於第二段:如果我理解正確,您有一組作業,用戶可以從中 select 並按一定的執行順序放置。 我會通過創建用戶選擇的每個作業類型的作業實例來處理它。 為了保持作業的順序,您可以將下一個作業的組名和作業名存儲在上一個作業的 JobDataMap 中。 然后你可以有一個通用的 JobListener,它注冊了所有的作業。 當作業執行時,偵聽器將收到通知,並將作業包作為參數傳遞。 JobListener 可以枚舉剛剛執行的作業的 JobDataMap。 如果它找到鍵為“nextjobname”的鍵值對,JobListener 將查詢調度程序以獲取該作業。 對作業包中的調度程序的引用。 如果調度程序返回給定名稱的 JobDetail 實例,則 JobListener 將執行它,完成時會收到通知,依此類推,直到它到達 JobDataMap 中具有“nextjobname”的作業。
或者,如果您不想擁有 Job Listeners,您可以擁有一個實現此功能的基本 Job class。您的所有作業都將派生自此 class 並將覆蓋其虛擬 Execute 方法。 您可以在重寫實現返回之前調用 base.Execute(context) 。

public class Basejob : IJob
{
    public virtual void Execute(JobExecutionContext context)
    {
        string nextJob = context.MergedJobDataMap["nextjobname"];
        JobDetail nextjob = context.Scheduler.GetJobDetail(context.MergedJobDataMap["nextjobname"],
                                           context.MergedJobDataMap["nextjobgroupname"]);
        if(nextjob != null)
        {
            context.Scheduler.ScheduleJob(nextjob, new SimpleTrigger(nextjob.Name + "trigger")); // this will fire the job immediately
        }
    }
}

public class MyJob : BaseJob
{
    public override void Execute(JobExecutionContext context)
    {
        //do work
        base.Execute(context);
    }
}

暫無
暫無

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

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