【问题标题】:Catching unhandled exception on separate threads在单独的线程上捕获未处理的异常
【发布时间】:2010-11-26 11:44:23
【问题描述】:

我正在使用以下事件在主 UI 线程中捕获未处理的异常。

Application.ThreadException 

不幸的是,它没有在单独的线程中捕获那些未处理的错误。我知道

AppDomain.CurrentDomain.UnhandledException

但是,这似乎会在触发时关闭应用程序,而前者不会。

有没有办法在不关闭应用程序的情况下处理单独线程上未处理的异常?

【问题讨论】:

  • 是的,请确保您的线程不会抛出未处理的异常。正如 Eric Lippert 所说:“最安全的做法是假设每个未处理的异常要么是致命异常,要么是未处理的愚蠢异常。在这两种情况下,正确的做法是立即取消进程。” blogs.msdn.com/b/ericlippert/archive/2010/11/23/…
  • 您忘记了那篇文章最精彩的部分:“正如 Ripley 所说,当出现问题时,您应该起飞并从轨道上对整个站点进行核爆炸;这是唯一确定的方法”
  • 有兴趣找文章的朋友,之前的链接已经失效了,可以去这里:web.archive.org/web/20101124205815/http://blogs.msdn.com/b/…

标签: c# exception-handling


【解决方案1】:

@Ani 已经回答了你的问题。尽管我不同意线程中未处理的异常应该终止应用程序。使用线程通常意味着您有某种服务器应用程序。将其关闭可能会导致很多用户愤怒。

我写了一篇关于正确异常处理的小文章:https://coderr.io/exception-handling

您应该始终捕获线程的异常。我通常使用以下模式:

  void ThreadMethod(object state)
  {
      try
      {
          ActualWorkerMethod();
      }
      catch (Exception err)
      {
          _logger.Error("Unhandled exception in thread.", err);
      }
  }

  void ActualWorkerMethod()
  {
      // do something clever
  }

通过将逻辑移动到单独的方法中并在线程方法中保留 try/catch 块,找到不能正确处理异常的线程方法要容易得多。

【讨论】:

  • 如果另一个线程上的未处理异常是由您正在使用的第 3 方组件的私有异步方法引发的,您如何解决这个问题?
  • 除非第三方库提供某种方式,否则您不能。至于异步方法(开始/结束),您需要在其中使用 catch。但是,您可以使用 AppDomain.UnhandledException 事件捕获异常(但不能挽救应用程序)。
【解决方案2】:

当然,您应该始终处理所有异常。但如果您目前无法这样做,您可以尝试以下方法:

应用程序将在 UnhandledException 事件处理程序之后崩溃/关闭。 您可以在事件处理程序中添加延迟来防止这种情况。没有例外的其他线程(例如主线程)可以继续。所以应用程序不会关闭并且可以继续。但是,出现异常的线程将保持睡眠状态。因此,您可能会遇到“内存/线程泄漏”。

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        // Log the exception, display it, etc
        Debug.WriteLine((e.ExceptionObject as Exception).Message);
        Thread.Sleep(100000000);
    }

目前没有更好的解决方案。 您可能会发现要更改配置文件,但我认为这同样肮脏:https://stackoverflow.com/a/15348736

【讨论】:

    【解决方案3】:

    是的,您必须手动捕获线程上的异常。

    但是,这段代码:

    void ThreadMethod(object state)
    {
        try
        {
            ActualWorkerMethod();
        }
        catch (Exception err)
        {
            _logger.Error("Unhandled exception in thread.", err);
        }
    }
    
    void ActualWorkerMethod()
    {
        // do something clever
    }
    

    可以使用PostSharp 简化为:

    [LogExceptions]
    void ActualWorkerMethod()
    {
        // do something clever
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-20
      • 2013-03-09
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 2017-11-25
      • 2013-06-16
      • 2014-09-02
      相关资源
      最近更新 更多