【问题标题】:How to reschedule Quartz job scheduler in C# dynamically from database?如何从数据库动态重新调度 C# 中的 Quartz 作业调度程序?
【发布时间】:2017-01-11 11:35:29
【问题描述】:

我在我的 C#.Net 网站中包含 Quartz.net 库,以根据某些条件自动发送电子邮件。我已经使用 RepeatForever() 开始了这项工作。我正在从数据库中获取调度程序的设置。现在,当作业已经开始时,无论如何都要检查数据库中调度程序的设置是否已更改,所以我还应该在我的方法中更新它们,以便调度程序以新设置动态运行?到目前为止,我已经这样做了:

public void StartJob()
    {
        var reminderSettings = GetReminderSettings();  //getting these settings from database
        var count = GetUnpaidInvoicesListCount();
        var intervalBtwnReminders = 0;
        if (reminderSettings?.RemindersGap != null)
        {
            intervalBtwnReminders = (int)(reminderSettings.RemindersGap);         
        }

        ISchedulerFactory schedFact = new StdSchedulerFactory();

        IScheduler sched = schedFact.GetScheduler();
        sched.Start();

        // create job
        IJobDetail job = JobBuilder.Create<EmailJob>()
                .WithIdentity("job1", "group1")
                .Build();

        // create trigger
        ITrigger trigger = TriggerBuilder.Create()
            .WithIdentity("trigger1", "group1")
            .WithSimpleSchedule(x =>
            {
                 x.WithIntervalInMinutes(intervalBtwnReminders ).RepeatForever();
            })
            .Build();

        sched.ScheduleJob(job, trigger);
    }

【问题讨论】:

    标签: c# .net quartz.net


    【解决方案1】:

    我写了一套方法让它更容易。 您无法使用新间隔编辑现有触发器,但可以将现有触发器替换为新触发器。 CreateTrigger 方法基于旧触发器创建新触发器并传输 TimesTriggered 计数。

    /// <summary>
    /// Create a new trigger based on a existing trigger.
    /// </summary>
    /// <param name="oldTrigger">the existing trigger</param>
    /// <param name="startNow">indicates if the trigger should start immediately after schedule</param>
    /// <param name="interval">the interval for the new trigger</param>
    /// <returns>Returns the new trigger</returns>
    public ITrigger CreateTrigger(ITrigger oldTrigger, bool startNow = false, TimeSpan? interval = null)
    {
        var builder = oldTrigger.GetTriggerBuilder();
        if (startNow)
            builder = builder.StartNow();
        if (interval.HasValue)
            builder = builder.WithSimpleSchedule(s => s
                .WithInterval(interval.Value)
                .RepeatForever());
    
        var newTrigger = builder.Build();
        var simpleTrigger = newTrigger as ISimpleTrigger;
        if(simpleTrigger != null)
        {
            var trigger = oldTrigger as ISimpleTrigger;
            if (trigger != null)
                simpleTrigger.TimesTriggered = trigger.TimesTriggered;
        }
    
        return newTrigger;
    }
    

    如何使用

    在此示例中,调度程序已在运行。

    // get the trigger
    var trigger = Scheduler.GetTrigger(new TriggerKey("trigger1", "group1"));
    
    // get your settings and set the interval
    var reminderSettings = GetReminderSettings();
    var intervalBtwnReminders = 0;
    if (reminderSettings?.RemindersGap != null)
    {
        intervalBtwnReminders = (int)(reminderSettings.RemindersGap);         
    }
    
    // reschedule the job with a new trigger and start it immediately.
    // if you don't want that it starts now, pass 'false' for the 'startNow' parameter
    Scheduler.RescheduleJob(trigger.Key, CreateTrigger(trigger, true, TimeSpan.FromMinutes(intervalBtwnReminders)));
    

    【讨论】:

    • 我没听懂,你能再解释一下你的解决方案吗?在哪里调用数据库进行设置?
    • @Harry.Naeem 我添加了更多解释,将参数timespan 重命名为interval 以使其更清晰。并添加了一个文档标题。我希望它现在更容易理解了。
    • 我应该在哪里使用 GetTrigger(),在旧触发器启动后 (sched.Start()) 或之后 (sched.ScheduleJob(job, trigger))?
    • @Harry.Naeem 这些都不是。您的应用程序只需要一个调度程序。 StartJob() 方法(命名次优)应该只注册您的作业/触发器并启动调度程序。然后,您需要记住调度程序作为参考,在您可以轻松访问它的地方。假设您执行了StartJob(),可能 5 分钟后,您调用了该示例。
    • 谢谢你,伙计,这就像一个魅力!您上一条评论中最重要的陈述是那么您需要记住调度程序作为参考,这帮助我解决了我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 2011-07-23
    • 2014-08-28
    • 2010-12-16
    • 1970-01-01
    相关资源
    最近更新 更多