如何在非UI线程抛出异常时保留堆栈跟踪信息

7

这样做是不好的形式,因为它不能保留堆栈跟踪:

try { /*... some code that can throw an exception ...*/ }
catch (Exception e)
{
    throw e; // ...Use "throw;" by itself instead
}

然而,如果在非UI线程捕获到异常,我希望将其重新引发到UI,并进行处理,以便用户能够接收到消息,如下所示:
try { /*... some code that can throw an exception ...*/ }
catch (Exception e)
{
    Dispatcher.Invoke((Action)(() => { throw; }));
}

然而,在这里我不能仅使用throw关键字,因为C#词法分析器(正确地)不认为throw语句位于catch块内。相反,我必须这样做:

try { /*... some code that can throw an exception ...*/ }
catch (Exception e)
{
    Dispatcher.Invoke((Action)(() => { throw e; }));
}

并重新抛出异常,这将导致其堆栈跟踪丢失。

是否有任何(简单)方法可以解决这个问题(我始终可以在准备切换线程时打包堆栈跟踪,但这似乎很不可靠)?

注意:我看到了此主题,但它仅在标题上与此内容相似。


1
你尝试过使用 Exception, string, Exception 构造函数抛出新的 Exception 吗?这样你的内部异常就会是原始异常。 - Daniel Kelley
你为什么要在第一时间使用try/catch,当你所做的只是重新抛出它呢?此外,如果您将PDB文件与EXE/DLL一起放置,堆栈跟踪将会跟随。 - Mats Magnem
重复?在 C# 中,如何重新抛出 InnerException 而不丢失堆栈跟踪? - vidstige
在这里,我建议退出 catch 块,然后调用。如果例如在调用的操作内抛出新异常,那么您将获得更易于理解的流程路径。 - vidstige
1个回答

4
通常的做法是抛出一个异常,并将原始异常作为InnerException包含在内。 Exception一个特殊的构造函数来实现这个
但如果你真的想这样做,而且你使用的是.Net 4.5,你可以使用ExceptionDispatchInfo来捕获异常的堆栈跟踪,然后重新抛出它到其他地方,而不重置堆栈跟踪。但在大多数情况下,使用旧方法将异常包装在新异常中可能更好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接