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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14653920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 07:21:07  来源:igfitidea点击:

How can I preserve the stack trace when exception is thrown on non-UI thread

c#wpfexception

提问by Michael

Doing this is bad form because it doesn't preserve a stack trace:

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

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

However, if the exception is caught on a non-UI thread, I want to do raise it back up to the UI and handle it so the user gets the message like so:

但是,如果异常是在非 UI 线程上捕获的,我想将其提升回 UI 并对其进行处理,以便用户获得如下消息:

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

However, I can't use the throw keyword by itself here because the C# lexer (correctly) doesn't think the throwstatement is inside of a catch. I have to instead do:

但是,我不能在这里单独使用 throw 关键字,因为 C# 词法分析器(正确地)认为throw语句不在catch 内。我必须这样做:

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

and re-throw the exception, which loses its stack trace.

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

Is there any (easy) way to get around this (I could always package the stack trace at the time the exception is ready to switch threads, but that seems hokey)?

有没有什么(简单的)方法可以解决这个问题(我总是可以在异常准备好切换线程时打包堆栈跟踪,但这似乎很糟糕)?

Note: I saw this threadbut it's similar in title only, not content.

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

采纳答案by svick

The usual way to do this is to throw a newexception, with the original included as InnerException. Exceptionhas a special constructor for this.

执行此操作的通常方法是抛出一个异常,并将原始异常包含为InnerException. Exception一个特殊的构造函数 this

But if you really want to do this and you're on .Net 4.5, you can use ExceptionDispatchInfoto capture the stack trace of the exception and then rethrowing it somewhere else without resetting the stack trace. But in most situations, using the old method of wrapping the exception in a new one is probably better.

但是如果你真的想这样做并且你在 .Net 4.5 上,你可以使用ExceptionDispatchInfo捕获异常的堆栈跟踪,然后将它重新抛出到其他地方而不重置堆栈跟踪。但在大多数情况下,使用将异常包装在新方法中的旧方法可能会更好。