在 Quartz.Net 中调度相关作业

发布于 2024-11-25 11:07:27 字数 461 浏览 1 评论 0原文

我需要一些帮助。我正在尝试弄清楚如何在 Quartz.Net 中安排工作。 Quartz 中的作业对应于我的 Web 应用程序中的任务,它们都是我的 Web 应用程序中作业的一部分。我希望用户能够按需启动作业(Web应用程序上下文)并使其立即运行或安排将来的作业,并且可能在给定的时间间隔内重复。我知道所有这些项目是如何在 Quartz 中单独完成的,但我很难将它们放在一起。

例如,在我的 Web 应用程序中,我可能有一项包含多个任务的工作,并且按特定顺序进行。我希望能够在quartz中安排这些任务,以便它们按照我的Web应用程序中确定的相同顺序执行。有人知道如何做到这一点吗?我读过 Quartz 文档,说要将下一个作业存储在 JobDataMap 中,只是在努力解决这个问题。

我目前正在等待创建 Quartz 作业,直到用户请求安排作业或运行它。您认为我应该创建作业并在 Web 应用程序中创建任务时触发,然后从任务对象中提取该信息以在 Quartz 中进行调度吗?

I need some help. I am trying to figure out how to schedule jobs in Quartz.Net. Jobs in Quartz correspond to tasks in my Web Application, which are each apart of a Job in my Web Application. I want users to be able to launch a Job (WebApplication Context) on demand and have it run immediately or schedule the job in the future and, to possibly repeat on a given interval. I know how all these items are accomplished in Quartz individually, but i am having a hard time putting it all together.

For example, in my web application, I may have a job with several task, in a specific order. I want to be able to schedule these tasks in quartz so that they execute in the same order determined in my Web Application. Does anybody have idea of how to do this? I have read up on Quartz documentation saying to store the next Job in the JobDataMap, Just struggling with it.

I am currently waiting to create Quartz jobs until a user requests to either schedule the Job or Run it. Do you think I should be creating the job and trigger on creation of the task in the Web App and then pulling that information from the task object for scheduling in Quartz?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

婴鹅 2024-12-02 11:07:27

您需要的是 JobChainingJobListener 类,它可以帮助您按照您想要的特定顺序为作业创建执行链。

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

What you need is the JobChainingJobListener class, which is there to help you create a chain of execution for your jobs in a specific order you desire..

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();
        }
    }
}
绅刃 2024-12-02 11:07:27

关于第二段:如果我理解正确的话,您有一组作业,用户可以从中选择并按一定的执行顺序放置。我将通过创建用户选择的每种作业类型的作业实例来实现此目的。为了保持作业的顺序,您可以将下一个作业的组名和作业名存储在上一个作业的 JobDataMap 中。然后你就可以拥有一个通用的JobListener,它向所有作业注册。当作业执行时,侦听器将收到通知,并将作业包作为参数传递。 JobListener可以枚举刚刚执行的作业的JobDataMap。如果找到带有“nextjobname”键的键值对,JobListener 将向调度程序查询该作业。对作业包中也可用的调度程序的引用。如果调度程序返回给定名称的 JobDetail 实例,JobListener 将执行它,并在完成时收到通知,依此类推,直到它到达 JobDataMap 中具有“nextjobname”的作业。
或者,如果您不想拥有作业侦听器,则可以拥有一个实现此功能的作业基类。您的所有作业都将从此类派生并覆盖其虚拟 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);
    }
}

On the second paragraph: If I understand you correctly, you have a set of jobs, from which the user can select and put in certain order of execution. I would approach it by creating a job instance of every job type selected by the user. In order to persist the order of the jobs, you can store the groupname and jobname of the next job in the JobDataMap of the previous job. Then you can have a generic JobListener, which is registered with all jobs. The listener will get notified when a job is executed and will be passed the job bundle as an argument. The JobListener can enumerate the JobDataMap of the job which has just been executed. If it finds a key-value pair with key "nextjobname", the JobListener will query the scheduler for this job. A reference to the scheduler of also available in the job bundle. If the scheduler returns an instance of JobDetail for the given name, the JobListener will execute it, will get notified when it completes and so on until it gets to a job with "nextjobname" in the JobDataMap.
Alternatively, if you don't want to have Job Listeners, you can have a base Job class which implements this functionality.All your jobs will derive from this class and will override its virtual Execute method. You can call base.Execute(context) just before the overriding implementation returns.

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文