繁体   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