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

时间:2013-06-25 13:10:30

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

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

有没有办法保证我能抓住任何发生的异常。

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

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

4 个答案:

答案 0 :(得分:5)

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

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

这实际上并没有让你解决任何问题 - 唯一明智的做法是在线程函数本身中正确处理异常。

答案 1 :(得分:2)

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

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

这个方法。 try-catch应该在任何thread-method

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

答案 2 :(得分:1)

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

另一种可能性是使用AOP(PostSharp会想到)。但是,捕获异常并不是唯一的目标。您需要找到一种方法来解决异常的原因。如果它是一个错误,该异常是有用的,并且记录足够。如果有更复杂的原因,您需要考虑并应用对策。不幸的是,没有“一般解决方案”。所以如果你事先没有抓住异常,我怀疑你可以做得很好。

答案 3 :(得分:0)

据我所知,.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
        }

    }