在所有Quartz .NET IInterruptableJob上触发中断

时间:2015-09-17 13:29:26

标签: c# quartz-scheduler quartz.net

我正在使用Quartz调度程序,并尝试在关闭应用程序时关闭所有作业。我有一份专业工作,可以帮助我做一个' Hold'或者'忙碌等待,基本上直到它得到一个条件,它坐在那里耐心等待。

由于新的集成点,这项工作是新的。该应用程序使用Topshelf作为服务运行,每当我们尝试关闭服务以升级它时,现在该作业正在运行,我们必须重新启动服务器以使其关闭。

无论如何,这里很奇怪,我有一个单一的作业类型,当我尝试使用作业FireInstanceIdJobKey尝试触发以下代码部分中的中断时:

_logger.InfoFormat("{0} scheduler interrupting listener", scheduler.SchedulerName);
scheduler.Interrupt(ListenerKeys.Realtime);

_logger.InfoFormat("{0} scheduler shutting down", scheduler.SchedulerName);
scheduler.Shutdown(true);

_logger.InfoFormat("{0} scheduler shut down", scheduler.SchedulerName);

我得到一个例外:

  

Job' Listeners.Realtime'不能被打断,因为它没有实现Quartz.IInterruptableJob

人们会认为这是直截了当的。但是,这是使用此作业键的唯一作业:

ListenerJob : BaseJob, IInterruptableJob
{
    // some other code referenced in ExecuteJob
    public void Interrupt()
    {
        _dequeuer.StopDequeing();
    }
}

我不知道如何实现它,所以我的问题变成了:Quartz中是否存在已知错误?是否存在组密钥和中断的问题?有没有办法告诉调度程序中断所有可中断的作业?还有其他选择吗?

更新

我决定从以下答案运行以下代码以获得更多诊断。 var接口确实包括IInterruptableJob

var jobs = scheduler.GetCurrentlyExecutingJobs().Where(x => Equals(x.JobDetail.Key, ListenerKeys.Realtime));

var job1 = jobs.First();

var interfaces = job1.JobDetail.JobType.GetInterfaces();

此外,我按照下面的建议运行了ReportInterruptableJob,它检查了程序集并确认了ListenerJob实现了接口。

UPDATE2:

好的,我去了git hub,并运行了确切的meshos。作为IInterruptableInterface的Job.JobInstance返回null,这就是我得到错误的原因。我不明白,我想,我是如何围绕实现IInterruptableJob的IJo形成JobInstance

UPDATE3:好的......所以我在引导程序中发现了一些使用JobWrapper<>的东西。我对此一无所知,但我确信这是其中的一部分。

2 个答案:

答案 0 :(得分:2)

所以我同意另一个答案(C Knight)可能关闭JobKey。

如果你已经实现了界面......并且你有正确的JobKey ..那么你就不应该得到那个例外。

以下是我打断工作的代码。我试图找到"找到钥匙"逻辑也是如此。

 private static void InterruptAJob(JobKey foundJobKey, IScheduler sched)
    {
        if (null != foundJobKey)
        {
            sched.Interrupt(foundJobKey);
        }
    }

APPEND

这是我找到工作密钥的代码。

我会从它开始..........放一些断点......看看你的JobKey是否在集合中。也许修改例行程序(在你找出魔术场所之后)按照一定的标准找到一个工作密钥......如果你找不到你期望找到的东西,就抛出一个例外。阿卡,不要"假设" JobKey存在.....但查询它并抛出相应的异常(或者如果没有找到匹配则写入相应的== null逻辑)....... vs"假设它必须是有"方法

再次,下面是" starter"代码.......我的概念验证只有一个工作,所以我没有必要具体。

private static JobKey FindaJobKey(IScheduler sched, ILogger logger)
{
    JobKey returnJobKey = null;

    IList<string> jobGroupNames = sched.GetJobGroupNames();

    if (null != jobGroupNames)
    {
        if (jobGroupNames.Count > 0)
        {
            GroupMatcher<JobKey> groupMatcher = GroupMatcher<JobKey>.GroupEquals(jobGroupNames.FirstOrDefault());
            Quartz.Collection.ISet<JobKey> keys = sched.GetJobKeys(groupMatcher);
            returnJobKey = keys.FirstOrDefault();

            if (null == returnJobKey)
            {
                throw new ArgumentOutOfRangeException("No JobKey Found");
            }
        }

    }

    Thread.Sleep(TimeSpan.FromSeconds(1));

    return returnJobKey;

}

APPEND:

也许是这样的:

private static JobKey FindJobKey(IScheduler sched, ILogger logger, string jobGroupName)
{
    JobKey returnJobKey = null;

    IList<string> jobGroupNames = sched.GetJobGroupNames();

    if (null != jobGroupNames)
    {
        string matchingJobGroupName = jobGroupNames.Where(s => s.Equals(jobGroupName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

        if (null != matchingJobGroupName)
        {
            GroupMatcher<JobKey> groupMatcher = GroupMatcher<JobKey>.GroupEquals(matchingJobGroupName);
            Quartz.Collection.ISet<JobKey> keys = sched.GetJobKeys(groupMatcher);

            if (null != keys)
            {
                if (keys.Count > 0)
                {
                    throw new ArgumentOutOfRangeException(string.Format("More than one JobKey Found. (JobGroupName='{0}')", jobGroupName));
                }
                returnJobKey = keys.FirstOrDefault();

                if (null != returnJobKey)
                {
                    throw new ArgumentOutOfRangeException(string.Format("No JobKey Found. (JobGroupName='{0}')", jobGroupName));
                }
            }
        }

    }

    Thread.Sleep(TimeSpan.FromSeconds(1));
    return returnJobKey;
}

另一个快速而又脏的&#34;看看你发生了什么&#34;方法

    private static void ShowJobs(IScheduler sched)
    {
        Console.WriteLine("");
        Console.WriteLine("ShowJobs : Start");
        GroupMatcher<JobKey> matcherAll = GroupMatcher<JobKey>.AnyGroup();
        Quartz.Collection.ISet<JobKey> jobKeys = sched.GetJobKeys(matcherAll);
        foreach (JobKey jk in jobKeys)
        {
            Console.WriteLine(string.Format("{0} : {1}", jk.Group, jk.Name));
        }
        Console.WriteLine("ShowJobs : End");
        Console.WriteLine("");

    }

APPEND:

也许以另一种方式来。我略微调整了一种方法。但又添了一个新的。 ReportIInterruptableJobs

查看ReportIInterruptableJobs报告的内容。

    private static void ShowJobs(IScheduler sched, ILogger logger)
    {
        Console.WriteLine("");
        Console.WriteLine("ShowJobs : Start");
        GroupMatcher<JobKey> matcherAll = GroupMatcher<JobKey>.AnyGroup();
        Quartz.Collection.ISet<JobKey> jobKeys = sched.GetJobKeys(matcherAll);
        foreach (JobKey jk in jobKeys)
        {
            Console.WriteLine(string.Format("{0} : {1}", jk.Group, jk.Name));
            IJobDetail jobData = sched.GetJobDetail(jk);
            if (null != jobData)
            {
                Console.WriteLine(string.Format("{0}", jobData.JobType.AssemblyQualifiedName));
            }
        }
        Console.WriteLine("ShowJobs : End");
        Console.WriteLine("");

    }

    private static void ReportIInterruptableJobs()
    {
        Type typ = typeof(IInterruptableJob);
        ICollection<Type> types = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(s => s.GetTypes())
            .Where(p => typ.IsAssignableFrom(p)).ToList();
        if (null != types)
        {
            foreach (Type t in types)
            {
                Console.WriteLine(string.Format("{0}", t.AssemblyQualifiedName));
            }
        }

    }

答案 1 :(得分:2)

您100%肯定JobKey ListenerJob实际上是Listeners.Realtime吗?是否会有一个使用JobKey的不同工作?在您致电Listeners.Realtime时,Interrupt()可以更新为其他值吗? Quartz绝对找到了JobKey的工作,因为如果Quartz根本找不到工作,它就不会抛出异常。它找到的工作没有实现IInterruptableJob。我会通过JobKey ListenerJob方法设置断点并检查Execute(IJobExecutionContext context)来仔细检查ListenerJob的{​​{1}}值。我的钱在context.JobDetail.Key不同。此外,我们可能会看到您JobKey的代码是什么有用。