我想在线程A中捕获异常,然后将异常对象传递给线程B,并从线程B中抛出它。这样安全吗?
主题A
try {
// Code that throws exceptions
} catch (Exception e) {
sendToOtherThread(e);
}
主题B
Exception e = receiveException();
throw e;
修改
为了清楚起见:我理解线程是如何工作的,以及我应该如何将对象引用从一个线程传递到另一个线程。问题更多的是从一个没有创建它的线程抛出一个异常对象是安全的,还是类Exception
本身或.NET处理它的方式有问题。
答案 0 :(得分:1)
如果考虑使用.NET 4.0,Task
抛出的任何异常会在Task
加入时自动传播到父线程。这是设计的,应该是非常安全的。看看这里:http://msdn.microsoft.com/en-us/library/dd997415.aspx
答案 1 :(得分: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);
}
...
}
答案 2 :(得分: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%安全的)。
答案 3 :(得分:0)
它应该是安全的,但很可能会终止线程B.
您的解决方案仅取决于您如何将异常对象从线程A传递到线程B. 如果要将其放在共享资源中,则需要锁定并释放该特定共享资源。除此之外,您的代码没有任何不安全因素。
只要您不访问线程中的任何共享资源,其他一切都应该是安全的。
答案 4 :(得分:0)
Exception
是一个类,因此是一个标准引用类型,如果你想在线程之间传递它(听起来有点奇怪),你需要确保没有其他人试图修改实例(特别是如果你创建自己的可变异常类型。)
解决方案A
你可以做一个Producer-Consumer拉模型
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
但是可能更好的想法是不使用拉模型,因为在这种情况下它可能浪费资源,而是推送具有线程安全可观察集合的模型。