2

我想在线程 A 中捕获异常,然后将异常对象传递给线程 B,然后从线程 B 中抛出它。这样安全吗?

线程 A

try {
    // Code that throws exceptions
} catch (Exception e) {
    sendToOtherThread(e);
}

线程 B

Exception e = receiveException();
throw e;

编辑

为了清楚起见:我了解线程是如何工作的,以及我应该如何将对象引用从一个线程传递到另一个线程。问题更多的是从一个没有创建异常对象的线程抛出异常对象是否安全,或者类Exception本身或 .NET 处理它的方式是否存在任何问题。

4

5 回答 5

1

如果您考虑使用 .NET 4.0,则 a 引发的任何异常都会Task在加入时自动传播到父线程Task。这是设计使然,应该是完全安全的。看看这里:http: //msdn.microsoft.com/en-us/library/dd997415.aspx

于 2012-07-04T10:25:07.977 回答
1

可以重新抛出从另一个线程接收到的异常(例如,在 BackgroundWorker 的 RunWorkerCompleted 事件处理程序中),但更常见的做法是将其包装在另一个异常中,以保留堆栈跟踪:

private void backgroundWorker1_RunWorkerCompleted(
    object sender, RunWorkerCompletedEventArgs e)
{
    // First, handle the case where an exception was thrown.
    if (e.Error != null)
    {
        throw new SomeException("... message ...", e.Error);
    }
    ...
}
于 2012-07-04T10:27:42.453 回答
0

你需要改变这个:

在线程 B

Exception e = receiveException();
throw new Exception("Write something here, for example: 'Received from other thread'", e); // so you keep the stack trace

但我会提防警告(我不完全确定这是 100% 安全的)。

于 2012-07-04T09:51:20.883 回答
0

它应该是安全的,但很可能它会终止线程 B。

您的解决方案仅取决于您如何将异常对象从线程 A 传递到线程 B。如果将其放入共享资源中,则需要锁定和释放该特定共享资源。除此之外,您的代码没有任何不安全之处。

只要您不访问线程中的任何共享资源,其他一切都应该是安全的。

于 2012-07-04T10:01:02.797 回答
0

Exception是一个类,因此是标准引用类型,如果你想在线程之间传递它(这听起来有点奇怪),你需要确保没有其他人试图修改实例(特别是如果你创建自己的可变异常类型)。

解决方案 A
你可以做一个 Producer-Consumer pull-model

BlockingCollection<Exception> bc = new BlockingCollection<Exception>();

// thread A - Producer
try
{
    ...
}
catch(Exception ex)
{
    bc.Add(ex);
}


//thread B - Consumer
try
{
    // Consume bc
    while (true)
    {
        var ex = bc.Take();
        //thread sleep
    }
}
catch (InvalidOperationException)
{
    // IOE means that Take()
    // was called on a completed collection and no
    // No more exceptions, restart checking    
}

解决方案 B
但可能更好的主意是不使用拉模型,因为在这种情况下它会浪费资源,而是使用具有线程安全的可观察集合的推模型。

于 2012-07-04T10:01:35.290 回答