您可以在不同的线程上重新引发 .NET 异常吗?
Posted
技术标签:
【中文标题】您可以在不同的线程上重新引发 .NET 异常吗?【英文标题】:Can you rethrow a .NET exception on a different thread? 【发布时间】:2010-11-21 04:05:39 【问题描述】:在 C# 中捕获一个线程上的异常,然后在另一个线程上重新抛出它是否合法且安全。
例如这合法吗
Exception localEx = null;
Thread mythread = new Thread() () =>
try
DoSomeStuff();
catch(Exception ex)
localEx = ex;
);
myThread.Start();
...
myThread.Join();
if(localEx != null)
throw localEx; // rethrow on the main thread
我认为这是合法的,但我很难找到任何可以证明这一点的文档。我发现的最接近的是在此处简要提及在线程之间传输异常:http://msdn.microsoft.com/en-us/library/ms229005.aspx
【问题讨论】:
你能把一个对象从一个线程传递到另一个线程吗? @Partial:当然可以。 【参考方案1】:是的,这是合法的。异常是(一般来说)没有线程关联的描述性对象。
你最好将你的线程异常包装在一个新的异常中:
throw new Exception("Something descriptive here", localEx);
这样,localEx 中的堆栈跟踪将被保留(作为新异常的InnerException
)。
【讨论】:
-1:您打算添加引文吗?如果是这样,我会投票赞成。 您的回答是“是的,这是合法的”。我认为还需要更多。您已将答案扩展到不需要反对票的程度。【参考方案2】:你正在做的不是重新抛出。这是您碰巧在变量中的异常实例的新抛出。即使您只使用单个线程,这也是一个坏主意,因为它使异常看起来像是来自“抛出”站点。对于多个线程,我不知道任何人会如何发现线程发生了变化。
【讨论】:
【参考方案3】:当然。在并行操作期间,System.AggregateException 被添加到 .NET 4 中专门用于该目的。
【讨论】:
【参考方案4】:我不明白为什么它不起作用,但您需要记住您实际上并没有重新抛出异常。您正在抛出一个新异常,它恰好是同一个异常对象。因此,例如,堆栈跟踪会说它是从“throw localEx;”抛出的。而不是原始异常的来源。
【讨论】:
谢谢。是的,重新抛出是错误的词。我将使用 localEx 作为内部异常来避免您提到的调用堆栈问题。【参考方案5】:这是合法的,它不是重新抛出,它是在另一个线程上抛出的新异常(具有相同的异常对象)
【讨论】:
【参考方案6】:我不知道你为什么认为它不合法。如果它是非法的,编译器肯定会捕获或者运行时会抛出异常。事实上,我使用这种模式。 @John 在使用后台线程调用 Web 服务的 Windows 窗体应用程序中,我使用这种方式。然后在 Application.ThreadException ***处理程序中处理异常,记录等。无需知道异常发生在哪个线程中。
【讨论】:
以上是关于您可以在不同的线程上重新引发 .NET 异常吗?的主要内容,如果未能解决你的问题,请参考以下文章