场合
好吧,正如你在下面看到的,我有一个主应用程序,创建一个线程,创建一堆后台工作者。当某个BG工作人员触发RunWorkerCompleted时,我有时最终会丢弃一个未处理的异常,(因为我已明确指出,但这不是问题)。
因此Logs清楚地显示我的UnhandledException处理程序已输入并报告异常。 我知道我故意滥用OnUnhandledException,方法是使用Console.Read()停止App退出。我故意 ,因为我希望在终止应用之前进行人工干预/检查。
public static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Logger.log("UNHANDLED EXCEPTION : " + e.ExceptionObject.ToString());
Mail.Sendmail("ADMIN ALERT : " + e.ExceptionObject.ToString());
Console.Read(); // Yes, this is an ungraceful trick, I confess.
}
然而,在手动退出之前假设只是“暂停”的结果是让应用程序保持活动状态,即线程仍在生成工作程序,并且运行就好像什么也没发生。 甚至Weirder:UnhandledException仍然会在它再次发生时不时被删除。并且它每次记录,表现得就像是一个普通的'尝试捕获。 (这是.Net 3.0之前的默认行为)
问题
那么,为什么一切都在发生,好像没有抛出UnhandledException,并且线程和BG一直在运行,好像什么也没发生? 我的猜测是,只要未完成OnUnhandledException处理程序,并且应用程序仍处于活动状态,所有仍处于活动状态的正在运行的线程将继续在自由世界中生存并完成其工作。
这给了我一个不好的诱惑,就是保持这个设计,作为一个尝试/捕获到unHandled Exception 。
我知道这不是一个整洁的想法,因为你永远不知道如果异常是严重的或可以跳过的东西。但是,我真的更喜欢我的程序一整天都在运行并观察日志报告/邮件警报,并自行决定是否需要重新启动。
由于这是一个需要全天候运行的服务器应用程序,因此我希望避免因轻微的仍然未处理的异常导致的错误和重复中断。
最大的优点是服务器程序在我们逐个跟踪未处理的异常时保持运行,并在发生时提供补丁来处理它们。
感谢您的耐心等待,请随时提供反馈。
PS:不,我没有抽烟。
答案 0 :(得分:3)
我的猜测是只要OnUnhandledException处理程序不是 完成后,应用程序仍处于活动状态,所有正在运行的线程仍然存在 活着继续生活在一个自由的世界里并且做好自己的工作。
正确。但是你的其他线程现在正在一个可能不稳定的过程中发挥作用。当发生未处理的异常时,有充分的理由终止应用程序。
我真的更喜欢我的程序继续运行
除了(潜在的)稳定性问题之外,您还会积累未处理处理中涉及的任何内容的暂停状态。我的猜测是,每当它发生时你至少会泄漏一个线程。你不能饶过他们太多。
所以这将是一个非常糟糕的设计,只会延迟崩溃。
答案 1 :(得分:2)
首先,您需要订阅UnhadledThreadException处理程序。在那里你不能“劫持”异常,但你可以访问它,也可以访问它所属的线程。你现在可以做的是将投掷线程暂停。线程还活着!! 然而,这是一个糟糕的,肮脏的黑客!不要这样做!
查看this article了解一些细节。
我建议将线程模型切换到TPL(设计保留)。在那里你可以访问那些丑陋的跨线程异常,并且可以优雅地处理/压制它。
答案 2 :(得分:1)
如果您希望允许BackgroundWorker线程失败而不会终止整个过程,那么可以采用更简洁的方法来执行此操作。
首先,拦截RunWorkerCompleted事件。当BackgroundWorker线程终止时,会引发此事件,通常是或通过未处理的异常。然后在事件处理程序中,检查未处理的异常:
// Runs when the BackgroundWorker thread terminates.
private void ThreadFinished(object sender, RunWorkerCompletedEventArgs e)
{
// Process any unhandled exception
if (e.Error != null)
{
this.LogError(e.Error.Message, e.Error.StackTrace, blah, blah);
通过这种方式,您可以让BackgroundWorker线程死掉并记录任何异常,而不会终止整个过程。