C# 在Quartz.net中处理JobExecutionException异常

C# 在Quartz.net中处理JobExecutionException异常,c#,exception-handling,quartz.net,C#,Exception Handling,Quartz.net,可能是个愚蠢的问题。。。但不管怎么说 我已经设置了quartz,可以安排作业,并且可以确认作业(实现IJob接口)正在工作 查看网站上的文档(教程第3课): execute方法允许抛出的唯一异常类型是JobExecutionException 我希望当发生我没有明确处理的异常时,它应该抛出JobExecutionException,这样我就可以将其记录到“父”应用程序中。我已经将代码包装在一个try-catch中,并抛出了JobExecutionException,但是现在该在哪里处理它呢 我不

可能是个愚蠢的问题。。。但不管怎么说

我已经设置了quartz,可以安排作业,并且可以确认作业(实现IJob接口)正在工作

查看网站上的文档(教程第3课):

execute方法允许抛出的唯一异常类型是
JobExecutionException

我希望当发生我没有明确处理的异常时,它应该抛出JobExecutionException,这样我就可以将其记录到“父”应用程序中。我已经将代码包装在一个try-catch中,并抛出了JobExecutionException,但是现在该在哪里处理它呢


我不会在任何地方调用execute方法,它由Quartz(在单独的线程上)处理。那么,当错误发生时,我该如何处理它呢。我真的不想接受作业中的错误

通常,您会按如下方式设置作业的执行方法:

try
{
    // the work you want to do goes here
}
catch (ExceptionTypeYouWantToHandle1 ex1)
{
    // handle exception
}
catch (ExceptionTypeYouWantToHandle2 ex2)
{
    // handle exception
}
// and so on
catch (Exception ex)
{
    // something really unexpected happened, so give up
    throw new JobExecutionException("Something awful happened", ex, false); // or set to true if you want to refire
}

此时,调度程序本身将把异常记录到它记录的任何位置(基于配置)

我通过使用基类捕获所有异常来解决这个问题:

public abstract class JobBase : IJob
{
    protected JobBase()
    {
    }

    public abstract void ExecuteJob(JobExecutionContext context);

    public void Execute(JobExecutionContext context)
    {
        string logSource = context.JobDetail.FullName;

        try
        {
            ExecuteJob(context);
        }
        catch (Exception e)
        {
           // Log exception
        }
    }
}
你的职业课应该是这样的:

public class SomeJob : JobBase
{
    public SomeJob()
    {
    }

    public override void ExecuteJob(JobExecutionContext context)
    {
        // Do the actual job here
    }
}

如前所述,在全局级别上“检测”JobExecutionException的正确方法是实现并注册一个iJobUnlistener,并检查JobWasExecuted()方法中的JobExecutionException参数是否为!=空

然而,我遇到的问题(从OP的附加评论判断,他也面临这个问题)是Quartz没有处理JobExecutionException(它应该处理的),这导致未处理的异常终止了应用程序

到目前为止,我使用的是Quartz.NET 2.0.1发行版(.NET3.5)包中的预编译DLL。为了弄清问题的根源,我引用了Quartz项目/源代码,令我惊讶的是,它突然起作用了

有趣的是,这是执行IJob并处理JobExecutionException的Quartz库代码

try {
    if (log.IsDebugEnabled) {
       log.Debug("Calling Execute on job " + jobDetail.Key);
    }
    job.Execute(jec);
    endTime = SystemTime.UtcNow();
} catch (JobExecutionException jee) {
    endTime = SystemTime.UtcNow();
    jobExEx = jee;
    log.Info(string.Format(CultureInfo.InvariantCulture, "Job {0} threw a JobExecutionException: ", jobDetail.Key), jobExEx);
} catch (Exception e) {
   // other stuff here...
}

下一件事是直接引用我新编译的DLL,这也很有效。可悲的是,我不能告诉你为什么这是有效的,我目前没有时间进一步深入,但也许这对某些人有帮助。也许其他人可以证实这一点,甚至做出解释。它可能与不同的目标平台(x86/64位)有关?

好的,我做了更多的研究,看起来我正在寻找JobListener。现在来了解它将如何处理异常。annnnd。。。。不走运。即使有侦听器,应用程序在引发异常时也会崩溃。救命啊@tardomatic如果将作业侦听器连接到作业/组名称,则无论作业成功或失败,都将调用侦听器。在抛出JeaExcExcExpRebug(基于检测错误)之后,SCORE将认为作业不完整(根据定义,石英认为作业完成,除非您触发JOB Exchange异常)。现在,当您在侦听器的JobWasExecuted()方法中时,您可以检查JobExecutionException参数以查看它是否已设置。现在你知道如果作业失败了,你可以选择在以后再次执行作业之前执行清理等任务。我已经很久没有使用过这个了,我没有可用的代码来测试它是否有效。不过值得怀疑的是,抛出JobExecutionException是个问题。我抛出了它,但Quartz没有处理它并记录它,正如您所提到的,它只是作为一个未处理的异常一直冒泡。。。。你不可能是认真的。。。把他们都抓起来不是最好的做法。。。最好是添加一个侦听器,并对出现异常的作业结束做出反应……最佳做法是让您的作业处理自己的异常。您是否建议为每种工作类型创建一个单独的侦听器来处理异常?我也遇到了类似的问题。你知道什么会对石英社区有这么大的价值吗?youtube视频系列+你的一个石英忍者的代码示例设置了一个完整(简单)的石英实现,包括jobStore、单元测试和一些调试,你故意引起并发现了许多常见的“gothchas”。@jvilalta当你知道哪一行可能抛出异常时,为什么不在那里捕捉它?是的,这是完全正确的-在方法的开头不是一个
try
,在方法的结尾是一个
catch
-但是.net强制执行这一操作的方式与java不一样,所以全局异常处理程序-我没有说全局
catch
-非常常见(就像您在控制台应用程序中使用
AppDomain
UnhandledException
-处理程序)和“最佳”最可重用的版本就是一个监听器来完成这个任务。这是一个很好的解决方案,可以在其他不同的quartz作业之间实现通用日志记录。谢谢!…你不是认真的…把它们都捕捉到不应该是最佳实践…最好添加一个监听器并对作业结束时出现异常做出反应…我不同意我遵循你的思路,想举个例子吗?(一个指向pastebin代码的链接就很好了)我只是想说,我已经为这个问题实现了几乎完全相同的解决方案。对于任何想知道@Andreasniedermir评论的人来说,可能有一个“一网打尽”的错误做法是正确的,但你不需要这样做。作业应该处理他们的异常,但是如果你有一个未捕获的异常,使用这个解决方案ion比简单地允许底层异常进一步传播更可取,因为这至少可以让您以后以“石英方式”处理该问题。@Tom我同意您的看法,该工具不需要坚持任何实践。但是,将异常处理分离给侦听器要方便得多(例如,您可以一般地这样做…)这是不正确的。catch(JobExecutionException jee){endTime=