当在非 UI 线程上引发异常时,如何保留堆栈跟踪

本文关键字:何保留 保留 跟踪 堆栈 UI 线程 异常 | 更新日期: 2023-09-27 17:56:57

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

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 语句不在捕获范围内。相反,我必须这样做:

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

并重新引发异常,这将丢失其堆栈跟踪。

是否有任何(简单的)方法可以解决此问题(我总是可以在异常准备好切换线程时打包堆栈跟踪,但这似乎是恶作剧)?

注意:我看到了这个线程,但它只是标题相似,而不是内容。

当在非 UI 线程上引发异常时,如何保留堆栈跟踪

执行此操作的常用方法是抛出一个新的异常,将原始异常作为InnerException包含在内。 Exception为此有一个特殊的构造函数。

但是,如果您确实想要执行此操作并且使用的是 .Net 4.5,则可以使用 ExceptionDispatchInfo 捕获异常的堆栈跟踪,然后将其重新引发到其他位置,而无需重置堆栈跟踪。但在大多数情况下,使用将异常包装在新方法中的旧方法可能更好。