【问题标题】:Catching exceptions caused in different threads [duplicate]捕获不同线程中引起的异常[重复]
【发布时间】:2013-06-22 07:19:40
【问题描述】:

以下示例是对我的问题的简化。在新线程中引发异常。如果我没有在线程中处理它,它不会被外部 try/catch 捕获并崩溃我的应用程序。

有什么方法可以保证我捕捉到任何发生的异常。

        try
        {
            new Thread(delegate()
                {
                    throw new Exception("Bleh"); // <--- This is not caught

                }).Start();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }

【问题讨论】:

    标签: c# multithreading exception-handling thread-safety


    【解决方案1】:

    一般来说,在线程本身中捕获异常是最容易的。

    但是如果你想从线程函数本身单独捕获异常(并且如果你可以使用Task 而不是旧的Thread 方法),你可以编写如下代码:

    var task = Task.Factory.StartNew(() =>
    {
        throw new Exception("Test");
    });
    
    task.ContinueWith(t => handleException(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
    

    这使用ContinueWith() 在第一个线程完成并发生异常后调用另一个方法,因此您可以记录异常或其他:

    static void handleException(AggregateException exception)
    {
        foreach (var ex in exception.Flatten().InnerExceptions)
            Console.WriteLine(ex.Message);
    }
    

    这并不能真正让您解决任何问题 - 唯一明智的做法是在线程函数本身中正确处理异常。

    【讨论】:

    • 非常好的处理方式。
    【解决方案2】:

    我是这么说的,我相信这是最安全的:

     var thread =   new Thread(MyMethod);
     thread.start();
    

    这个方法。 try-catch 应该在任何线程方法中

     private void MyMethod()
     {
        try
        {
            {
                throw new Exception("Bleh");//<--- This's not caught => now it is caught :)
            }
        }
        catch (Exception ex)
        {
            Logger.Log(ex.ToString());
        }
    }
    

    【讨论】:

    • 是的,这是正确的做法,但我正试图找出一种几乎可以在全球范围内捕获的方法。
    【解决方案3】:

    使用AppDomain.UnhandledExceptionApplication.ThreadExceptionDispatcher.UnhandledException。这取决于应用程序的实际类型。

    另一种可能性是使用 AOP(想到了PostSharp)。但是,捕获异常并不是唯一的目标。您需要找到解决异常原因的方法。如果它是一个错误,那么异常是有帮助的并且足够记录。如果有更复杂的原因,您需要考虑并采取对策。不幸的是,没有“通用解决方案”。因此,如果您没有事先捕获异常,我怀疑您是否能很好地采取行动。

    【讨论】:

    • 这允许我记录异常但异常仍然失败并导致应用程序崩溃。
    • 是的,我知道我应该在线程本身中捕获异常,但在更复杂的开发中,我可能会错过一些东西,我不希望该异常仅仅因为我忘记了一个尝试/捕捉。
    • 好吧,有错误的应用程序崩溃了。您对此无能为力,因为发生异常后,应用程序可能处于未知状态。那你会怎么做?为了防止它崩溃,还有其他方法:单元测试、调试、日志记录……
    • 最好是崩溃而不是执行无效状态..
    【解决方案4】:

    据我了解,.Net 不允许在两个线程之间进行通信。因为线程彼此隔离。您可以通过简单的方式实现这一点,我不知道它适合您的程度。如果有用请标记答案。

    public  Exception exception;
    
    private void button1_Click(object sender, EventArgs e)
    {
            try
            {
                new Thread(delegate()
                {
                    try
                    {
                        throw new Exception("Bleh"); // <--- This is not caught
                    }
                    catch (Exception e)
                    {
                        exception = e;
                    }
    
                }).Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
    
            if (exception != null)
            {
                //your code here
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-24
      • 2014-05-20
      • 2021-04-27
      • 1970-01-01
      • 2013-06-16
      • 2014-07-09
      • 1970-01-01
      • 2017-07-11
      相关资源
      最近更新 更多