在所有 Quartz .NET IInterruptableJob 上触发中断 [英] Trigging Interrupt on all Quartz .NET IInterruptableJob

查看:80
本文介绍了在所有 Quartz .NET IInterruptableJob 上触发中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Quartz 调度程序,并尝试在关闭应用程序时关闭所有作业.我有一项特殊工作,它会等待"或忙碌等待",基本上直到它出现状况时,它才会耐心地坐在那里等待.

I'm working with Quartz scheduler, and attempting to close all jobs on shutdown of the app. I have one specialty job that does a 'Hold' or 'Busy-wait', basically until it gets a condition it sits there waiting patiently.

这项工作是新的,因为有一个新的集成点.该应用程序使用 Topshelf 作为服务运行,每当我们尝试关闭服务以升级它时,既然此作业正在运行,我们最终必须重新启动服务器以使其关闭.

This job is new, due to a new integration point. The app is run as a service using Topshelf, and whenever we try to shutdown the service to upgrade it, now that this job is running, we have to end up restarting the server to get it to shutdown.

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

Anyhow, here it gets weird, I have a single jobtype, and when i try to trigger the interrupt in the following section of code using the jobs FireInstanceId or JobKey:

_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);

我得到一个例外:

作业 'Listeners.Realtime' 不能被中断,因为它没有实现 Quartz.IInterruptableJob

Job 'Listeners.Realtime' can not be interrupted, since it does not implement Quartz.IInterruptableJob

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

One would assume this is straight forward. However Here is the ONLY job that uses this job key:

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

我想说这就是你实现它的方式,所以我的问题变成了:Quartz 中是否存在已知的错误?组键和中断可能有问题吗?有没有办法告诉调度程序中断所有可中断的作业?有没有替代品?

I'd go out on a limb and say that's how you implement it, so my question becomes: is there a known bug in Quartz? Is there an issue with group-keys and interrupts maybe? Is there just a way to tell the scheduler to interrupt ALL jobs that are interruptable? Is there an alternative?

更新

我决定运行以下代码以从以下答案中获得更多诊断信息.var 接口实际上包括 IInterruptableJob

I decided to run the following code for more diagnostics from below answers. var interfaces does in fact include 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 实现了接口.

Additionally, I ran ReportInterruptableJob as suggested below, which checked the assembly and confirmed ListenerJob implements the interface.

更新2:

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

Ok, I went out to git hub, and ran the exact meshos. Job.JobInstance as IInterruptableInterface returns null, which is why I get the error. What I don't understand I guess, I how the JobInstance is formed around the IJo which does implement IInterruptableJob

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

UPDATE3: Ok.... So I found something in the bootstrap that is using JobWrapper<>. I know nothing about it, but Im sure that is part of it.

推荐答案

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

So I agree with the other Answer (C Knight) that the JobKey may be off.

如果你已经实现了接口......并且你有正确的 JobKey..那么你不应该得到那个异常.

If you've implemented the interface...and you have the right JobKey..then you should not get that exception.

以下是我用于中断工作的代码.我也在尝试找到findthekey"逻辑.

Below is the code I have for the interrupting a job. I'm trying to find the "findthekey" logic as well.

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

附加

这是我查找工作密钥的代码.

Here is my code for finding a job key.

我会从它开始.......放一些断点......看看你的JobKey是否在集合中.也许修改例程(在你找出神奇的地方之后)以按特定标准找到工作关键......如果你没有找到你期望找到的东西,则抛出异常.也就是,不要假设" JobKey 存在.....但是查询它并抛出适当的异常(或者如果没有找到匹配,则编写适当的 == null 逻辑)......与假设它必须在那里"方法.

I would start with it..........put some breakpoints...and see if your JobKey is in the collection. Maybe modify the routine (after you figure out the magic-places) to find a job key by a certain criteria..and throw an exception if you don't find what you're expecting to find. Aka, don't "assume" the JobKey exists.....but query for it and throw the appropriate exception (or write the appropriate == null logic if no match is found).......vs the "assume it has to be there" approach.

同样,下面是入门"代码.......我的概念证明只有一项工作,所以我不必具体.

Again, the below is "starter" code.......my Proof of Concept only had one job in it, so I didn't have to be specific.

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;

}

附加:

也许是这样的:

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

另一种快速而肮脏的看看你在做什么"的方法.

Another quick and dirty "look at what you got going on" method.

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

    }

附加:

也许可以换一种方式.我稍微调整了一种方法.但是又加了一个.报告IInterruptableJobs

Maybe come at it another way. I slightly adjusted one method. But added a new one. ReportIInterruptableJobs

查看 ReportIInterruptableJobs 报告的内容.

See what ReportIInterruptableJobs reports.

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

    }

这篇关于在所有 Quartz .NET IInterruptableJob 上触发中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆