【问题标题】:C# UnhandledException from another thread keeps looping来自另一个线程的 C# UnhandledException 不断循环
【发布时间】:2012-08-26 20:12:44
【问题描述】:

我有一个非常简单的线程。 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异常行。

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

提前谢谢,我很困惑,不知道为什么会这样。

【问题讨论】:

  • 在未捕获的异常之后,线程不可能继续执行。它会运行什么代码?抛出异常的全部目的是专门防止下一行代码执行。这就像在代码中出现return 之后试图留在函数中一样。我不知道你为什么认为你需要这样做,但我很确定你是从某个地方的根本误解开始的。
  • 嗯,你让我信服了,没办法弥补。这将是一个非常严重的 CLR 错误。请记录您使用的 .NET 版本并发布启动线程并引发异常的代码,以便每个人都可以在自己的机器上重现此代码。

标签: c# multithreading visual-studio-2010 infinite-loop unhandled-exception


【解决方案1】:

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

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

i = 1 / 0;
foo(i);

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

基本上,不要尝试捕获异常,除非将其作为引发异常的代码设计的一部分。这只是没有意义,无论您的外部问题是什么,都可能有一种明智的方法来解决。

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

  1. 获取锁
  2. 修改一些对象
  3. 解除锁定

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

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

好的,那我如何杀死 CurrentDomainOnUnhandledException 中的线程,使其停止循环异常?

通常这不是您想要做的。如果那个线程持有锁怎么办?如果该线程分配了它需要释放的内存怎么办?

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

【讨论】:

    猜你喜欢
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    相关资源
    最近更新 更多