简体   繁体   English

劫持UnhandledException以保持多线程应用程序运行

[英]Hijacking UnhandledException to keep Multi-Threaded Application Running

Situation 情况
Well, as you can see below, I have a main App, creating a thread, which creates a bunch of background workers. 好吧,正如你在下面看到的,我有一个主应用程序,创建一个线程,创建一堆后台工作者。 When the RunWorkerCompleted is fired on some BG worker, I sometimes end up dropping an Unhandled Exception, (for a reason I have clearly pinpointed, but this is not the matter). 当一些BG工作人员触发RunWorkerCompleted时,我有时最终会丢弃一个未处理的异常,(因为我明确指出了这个原因,但这不是问题)。

建筑

So the Logs clearly show that my UnhandledException handler is entered and reports the exception. 因此,Logs清楚地显示我的UnhandledException处理程序已输入并报告该异常。 I know I am deliberately misusing the OnUnhandledException by stopping the App from exiting, using a Console.Read(). 我知道我故意滥用OnUnhandledException,方法是使用Console.Read()停止App退出。 I did it on purpose because I want a human intervention/check before terminating the 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.
    }

However, what was supposed just to be a "pause" before manual exit turned out to keep the App alive, ie, the Thread is still generating workers, and running as if nothing happened . 然而,在手动退出之前假设只是“暂停”的结果是让应用程序保持活动状态,即,线程仍在生成工作程序,并且运行就像没有发生任何事情一样 Even Weirder : The UnhandledException is still being dropped from time to time when it happens again. 甚至Weirder:UnhandledException仍然会在它再次发生时不时被删除。 And it is logged each time, behaving just as if it was a plain ol' try catch. 并且它每次记录,表现得就像是一个普通的'尝试捕获。 (This was the default behaviour before .Net 3.0) (这是.Net 3.0之前的默认行为)

Question
So, why is everything happening as if the UnhandledException was not thrown, and the thread and BG's keeping running as if nothing happened ? 那么,为什么一切都在发生,好像没有抛出UnhandledException,并且线程和BG一直在运行,好像什么也没发生? My guess is that as long as the OnUnhandledException handler is not done, and the App is still alive, all running threads that are still alive keep on living in a free world and doing their job. 我的猜测是,只要OnUnhandledException处理程序没有完成,并且App仍处于活动状态,所有仍处于活动状态的正在运行的线程将继续生活在一个自由的世界中并完成自己的工作。

This gives me a bad temptation, which is to keep this design, as a try/catch to unHandled Exception . 这给了我一个糟糕的诱惑,就是保持这个设计,作为一个尝试/捕获到unHandled Exception
I know this is not a tidy idea, as you never know if the exception is serious or something that could be skipped. 我知道这不是一个整洁的想法,因为你永远不知道异常是否严重或可以跳过的东西。 However, I would really prefer my program to keep running all day and watch the log report / mail alerts and decide for myself if it needs to be restarted or not. 但是,我真的更喜欢我的程序一整天都在运行并观察日志报告/邮件警报,并自行决定是否需要重新启动。 As this is a server application that needs to be running 24/7 I wanted to avoid ill-timed and repetitive interruptions due to minor still unhandled exceptions. 由于这是一个需要全天候运行的服务器应用程序,因此我希望避免因轻微的仍然未处理的异常导致的错误和重复中断。 The biggest advantage to that being that the server program keeps running while we are tracking down unhandled exceptions one by one and deliver patches to handle them as they occur. 最大的优点是服务器程序在我们逐个跟踪未处理的异常时保持运行,并在它们发生时提供补丁来处理它们。

Thank you for your patience, and please feel free to give feedback. 感谢您的耐心等待,请随时提供反馈。

PS : No, I did not smoke pot. PS: 不,我没有抽烟。

My guess is that as long as the OnUnhandledException handler is not done, and the App is still alive, all running threads that are still alive keep on living in a free world and doing their job. 我的猜测是,只要OnUnhandledException处理程序没有完成,并且App仍处于活动状态,所有仍处于活动状态的正在运行的线程将继续生活在一个自由的世界中并完成自己的工作。

Correct. 正确。 But your other threads are now doing their job in a potentially unstable process. 但是你的其他线程现在正在一个可能不稳定的过程中发挥作用。 There are good reasons for terminating the App when an unhandled exception happens. 当发生未处理的异常时,有充分的理由终止应用程序。

I would really prefer my program to keep running 我真的更喜欢我的程序继续运行

Besides the (potential) stability problems, you would accumulate the halted state of whatever is involved in the unhandled handling. 除了(潜在的)稳定性问题之外,您还会积累未处理处理中涉及的任何内容的暂停状态。 My guess is that you would at least leak a Thread each time it happens. 我的猜测是,每当它发生时你至少会泄漏一个线程。 And you can't spare too many of them. 你不能饶过他们太多。

So it would be a very bad design, and only delay the crashing. 所以这将是一个非常糟糕的设计,只会延迟崩溃。

First of all you need to subscribe the UnhadledThreadException handler. 首先,您需要订阅UnhadledThreadException处理程序。 There you can not "Hijack" the exception, but you have access to it and also to the thread it belongs. 在那里你不能“劫持”异常,但你可以访问它,也可以访问它所属的线程。 What you can do now is putting the throwing Thread into suspetion. 你现在可以做的是将投掷线程暂停。 The Thread will be still alive!! 线程还活着!! This however is a bad, dirty hack! 然而,这是一个糟糕的,肮脏的黑客! Do not do this! 不要这样做!

Take a look at this article for some details. 看一下这篇文章的一些细节。

I recommend switching your threading model to TPL (design remains). 我建议将线程模型切换到TPL(设计保留)。 There you have access to those ugly cross-thread excepions and can handle/supress em gracefully. 在那里你可以访问那些丑陋的跨线程异常,并且可以优雅地处理/抑制它们。

If you want to allow a BackgroundWorker thread to fail without killing the whole process, there's a cleaner way to do this. 如果您希望允许BackgroundWorker线程失败而不会终止整个过程,那么有一种更简洁的方法可以执行此操作。

First, intercept the RunWorkerCompleted event. 首先,拦截RunWorkerCompleted事件。 This event is raised when the BackgroundWorker thread terminates, either normally or via an unhandled exception . 当BackgroundWorker线程正常终止或通过未处理的异常终止时,将引发此事件。 Then in your event handler, check for the unhandled exception: 然后在事件处理程序中,检查未处理的异常:

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

In this way, you can let the BackgroundWorker thread die and log any exception without terminating the whole process. 通过这种方式,您可以让BackgroundWorker线程死掉并记录任何异常,而不会终止整个过程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM