捕获在不同线程中引起的异常

本文关键字:异常 线程 | 更新日期: 2023-09-27 18:19:46

下面的例子简化了我的问题。在新线程中引发异常。如果我没有在线程中处理这个问题,它就不会被外部try/catch捕获,并使我的应用程序崩溃。

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

        try
        {
            new Thread(delegate()
                {
                    throw new Exception("Bleh"); // <--- This is not caught
                }).Start();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }

捕获在不同线程中引起的异常

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

但是,如果您想从线程函数本身单独捕获异常(并且如果您可以使用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);
}

这并不能真正让你修复任何事情——唯一明智的方法是在线程函数本身中正确处理异常。

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

 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());
    }
}

使用AppDomain.UnhandledException、Application.ThreadException或Dispatcher.UnhandledException。这取决于应用程序的实际类型。

另一种可能性是使用AOP(脑海中浮现出PostSharp)。然而,捕捉异常并不是唯一的目标。您需要找到一种方法来修复异常的原因。如果它是一个bug,那么异常是有帮助的,并且日志记录就足够了。如果有更复杂的原因,你需要思考并采取对策。不幸的是,没有"通用的解决方案"。所以,如果你事先没有发现异常情况,我怀疑你是否能很好地采取行动。

根据我的理解,.Net不允许在两个线程之间进行通信。Beacause线程彼此隔离。你可以用一种简单的方式做到这一点,我不知道它对你有多合适。如果答案有用,请把它标记出来。

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
        }
    }