编程语言
首页 > 编程语言> > c#-在所有Quartz .NET IInterruptableJob上触发中断

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

作者:互联网

我正在使用Quartz Scheduler,并尝试在应用程序关闭时关闭所有作业.我有一项专门的工作,它会执行“保持”或“忙碌等待”,基本上会等到出现状况时才耐心等待.

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

无论如何,这里变得很奇怪,我只有一个作业类型,当我尝试使用作业FireInstanceId或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);

我有一个例外:

Job ‘Listeners.Realtime’ can not be interrupted, since it does not implement 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. Job.JobInstance作为IInterruptableInterface返回null,这就是为什么我得到此错误.我不明白的是,我是如何在确实实现IInterruptableJob的IJo周围形成JobInstance的

UPDATE3:好的….因此,我在引导程序中找到了使用JobWrapper<>的内容.我对此一无所知,但我确定这是其中的一部分.

解决方法:

因此,我同意另一个答案(C Knight)的观点,即JobKey可能已关​​闭.

如果您已经实现了接口…并且您拥有正确的JobKey ..那么您就不应获得该异常.

以下是我中断工作的代码.我也试图找到“ findthekey”逻辑.

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

附加

这是我找到工作钥匙的代码.

我将从它开始……….输入一些断点…,然后查看您的JobKey是否在集合中.也许可以修改例程(在找出魔术位置之后),以根据特定条件查找作业密钥.如果找不到所需的内容,则抛出异常.再说一遍,不要“假设” JobKey存在…..但是查询它并抛出适当的异常(或者,如果找不到匹配项,则编写适当的== null逻辑).假设它必须存在”方法.

再次,下面是“入门”代码…….我的概念证明只从事一项工作,因此我不必具体说明.

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

另一种快速而肮脏的方法“看看发生了什么”.

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

    }

附加:

也许换一种方式.我稍微调整了一种方法.但是增加了一个新的.
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));
            }
        }

    }

标签:quartz-net,quartz-scheduler,c
来源: https://codeday.me/bug/20191027/1947957.html