2

我有一个非常简单的线程。Thread 对象所做的唯一事情是throw new Exception();. 我这样做的原因是因为我需要测试如果在我的应用程序的单独线程中发生异常会发生什么。我已经用“真正的”运行时异常对此进行了测试,我的问题是一样的。

在调用线程之前我要做的是:

AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
Application.Current.DispatcherUnhandledException += CurrentOnDispatcherUnhandledException;

//To handle exceptions in another thread
private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
    //Do nothing ignore exception
}

//To handle all exceptions in main thread
private static void CurrentOnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs dispatcherUnhandledExceptionEventArgs)
{
    dispatcherUnhandledExceptionEventArgs.Handled = true;
}

当该线程确实抛出异常时,它首先会按CurrentDomainOnUnhandledException应有的方式命中,然后不会命中CurrentOnDispatcherUnhandledException。在CurrentDomainOnUnhandledException堆栈之后立即返回到抛出异常并再次抛出异常的线程,执行同一行。它永远不会停止这样做。这基本上是一个永无止境的循环,我不知道为什么。

UnhandledExceptionEventArgs 没有要设置的属性,也就是说我们已经处理了异常,我很确定这是问题的一部分。

我在做什么错,如何在这个线程中捕获这个 UnhandledException,并让线程继续执行(首选)或中止/杀死线程(不是首选),以便它不会继续执行 throw new exception 行。

我已经通过调试和发布对此进行了测试(确保发布的调试信息设置为无),这仍然发生在两个版本中,异常继续一遍又一遍地发生。

在此先感谢,我很困惑,不知道为什么会这样。

4

1 回答 1

1

当这个线程确实抛出异常时,它首先会像它应该的那样命中 CurrentDomainOnUnhandledException,然后它不会命中 CurrentOnDispatcherUnhandledException。在 CurrentDomainOnUnhandledException 之后,堆栈然后返回到抛出异常并再次抛出异常的线程,执行同一行。它永远不会停止这样做。这基本上是一个永无止境的循环,我不知道为什么。

您从未处理过异常。您刚刚返回到最初出错的相同代码。说代码是这样做的:

i = 1 / 0;
foo(i);

并假设您以零错误捕获除法,但在处理程序中,您除了返回之外什么都不做。好吧,你期望会发生什么?代码遇到了一个致命错误,导致无法取得进一步进展,而您没有采取任何措施来修复它。i应该包含什么值?!

本质上,不要试图捕获异常,除非作为抛出异常的代码设计的一部分。这只是没有意义,无论您的外部问题是什么,都可能有一种明智的方法来做到这一点。

但是如果一个线程严重失败,它的进程也会严重失败。这就是线程的本质——没有隔离。考虑:

  1. 获取锁
  2. 修改一些对象
  3. 释放锁

如果在步骤 2 中途抛出异常会发生什么?如果您的异常处理程序不释放锁,则尝试获取它的下一个线程将永远等待。如果您的异常处理程序确实释放了锁,则获取它的下一个线程将访问一个已部分修改且可能处于不一致状态的对象。因此,异常处理程序必须做出明智的决定,了解引发异常的代码,以及在释放引发异常时持有的任何锁之前要做什么。

如果你要捕捉异常,你必须弄清楚根本问题是什么并修复它。一般来说,只有完全理解引发异常的代码才能做到这一点。没有通用的方法可以做到这一点,因为没有通用的方法来修复可能损坏的对象。

好的,那么我如何杀死 CurrentDomainOnUnhandledException 中的线程以便它停止循环异常?

一般来说,这不是你想要做的。如果那个线程持有锁怎么办?如果该线程分配了它需要释放的内存怎么办?

如果您需要这种隔离,请使用进程,而不是线程。

于 2012-09-01T10:07:22.377 回答