我正在使用Quartz调度程序,并尝试在关闭应用程序时关闭所有作业。我有一份专业工作,可以帮助我做一个' Hold'或者'忙碌等待,基本上直到它得到一个条件,它坐在那里耐心等待。
由于新的集成点,这项工作是新的。该应用程序使用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'不能被打断,因为它没有实现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<>的东西。我对此一无所知,但我确信这是其中的一部分。
答案 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
的代码是什么有用。