捕获不同线程中引起的异常[重复]

Posted

技术标签:

【中文标题】捕获不同线程中引起的异常[重复]【英文标题】: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());
        

【问题讨论】:

【参考方案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.UnhandledException、Application.ThreadException 或Dispatcher.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
        

    

【讨论】:

以上是关于捕获不同线程中引起的异常[重复]的主要内容,如果未能解决你的问题,请参考以下文章

捕获多个异常-C# [重复]

在iOS中捕获崩溃和异常[重复]

python单元测试中的assertRaises没有捕获异常[重复]

捕获调用异步方法C#的异常[重复]

拦截 C# 中的所有异常,即使它们已经被捕获 [重复]

捕获重复条目异常