如何在不丢失C#中的堆栈跟踪的情况下抛出InnerException? ﹏ヽ暗。殇╰゛Y 2022-11-28 10:52 128阅读 0赞 本文翻译自:[How to rethrow InnerException without losing stack trace in C\#?][How to rethrow InnerException without losing stack trace in C] *I am calling, through reflection, a method which may cause an exception.* **我正在通过反射调用可能导致异常的方法。** *How can I pass the exception to my caller without the wrapper reflection puts around it?* **在没有包装反射的情况下,如何将异常传递给调用者?** *I am rethrowing the InnerException, but this destroys the stack trace.* **我抛出了InnerException,但是这破坏了堆栈跟踪。** *Example code:* **示例代码:** public void test1() { // Throw an exception for testing purposes throw new ArgumentException("test1"); } void test2() { try { MethodInfo mi = typeof(Program).GetMethod("test1"); mi.Invoke(this, null); } catch (TargetInvocationException tiex) { // Throw the new exception throw tiex.InnerException; } } -------------------- ### \#1楼 ### 参考:[https://stackoom.com/question/eVx/如何在不丢失C-中的堆栈跟踪的情况下抛出InnerException][https_stackoom.com_question_eVx_C-_InnerException] -------------------- ### \#2楼 ### public static class ExceptionHelper { private static Action<Exception> _preserveInternalException; static ExceptionHelper() { MethodInfo preserveStackTrace = typeof( Exception ).GetMethod( "InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic ); _preserveInternalException = (Action<Exception>)Delegate.CreateDelegate( typeof( Action<Exception> ), preserveStackTrace ); } public static void PreserveStackTrace( this Exception ex ) { _preserveInternalException( ex ); } } *Call the extension method on your exception before you throw it, it will preserve the original stack trace.* **在抛出异常之前对扩展方法进行调用,它将保留原始堆栈跟踪。** -------------------- ### \#3楼 ### *In **.NET 4.5** there is now the [`ExceptionDispatchInfo`][ExceptionDispatchInfo] class.* **在.NET 4.5中 ,现在有了[`ExceptionDispatchInfo`][ExceptionDispatchInfo]类。** *This lets you capture an exception and re-throw it without changing the stack-trace:* **这使您可以捕获异常并重新引发它,而无需更改堆栈跟踪:** try { task.Wait(); } catch(AggregateException ex) { ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); } *This works on any exception, not just `AggregateException` .* **这适用于任何异常,而不仅仅是`AggregateException` 。** *It was introduced due to the `await` C\# language feature, which unwraps the inner exceptions from `AggregateException` instances in order to make the asynchronous language features more like the synchronous language features.* **它是由于`await` C#语言功能而引入的,该功能从`AggregateException`实例解包了内部异常,以使异步语言功能更像同步语言功能。** -------------------- ### \#4楼 ### *Guys, you are cool.. I'm gonna be a necromancer soon.* **伙计们,你很酷..我很快就会成为一个死灵法师。** public void test1() { // Throw an exception for testing purposes throw new ArgumentException("test1"); } void test2() { MethodInfo mi = typeof(Program).GetMethod("test1"); ((Action)Delegate.CreateDelegate(typeof(Action), mi))(); } -------------------- ### \#5楼 ### *It **is** possible to preserve the stack trace before rethrowing without reflection:* **这是可能的,而不反射重新抛出之前保存堆栈跟踪:** static void PreserveStackTrace (Exception e) { var ctx = new StreamingContext (StreamingContextStates.CrossAppDomain) ; var mgr = new ObjectManager (null, ctx) ; var si = new SerializationInfo (e.GetType (), new FormatterConverter ()) ; e.GetObjectData (si, ctx) ; mgr.RegisterObject (e, 1, si) ; // prepare for SetObjectData mgr.DoFixups () ; // ObjectManager calls SetObjectData // voila, e is unmodified save for _remoteStackTraceString } *This wastes a lot of cycles compared to calling `InternalPreserveStackTrace` via cached delegate, but has the advantage of relying only on public functionality.* **与通过缓存的委托调用`InternalPreserveStackTrace`相比,这浪费了很多周期,但是具有仅依赖于公共功能的优点。** *Here are a couple of common usage patterns for stack-trace preserving functions:* **以下是堆栈跟踪保留功能的两种常见用法模式:** // usage (A): cross-thread invoke, messaging, custom task schedulers etc. catch (Exception e) { PreserveStackTrace (e) ; // store exception to be re-thrown later, // possibly in a different thread operationResult.Exception = e ; } // usage (B): after calling MethodInfo.Invoke() and the like catch (TargetInvocationException tiex) { PreserveStackTrace (tiex.InnerException) ; // unwrap TargetInvocationException, so that typed catch clauses // in library/3rd-party code can work correctly; // new stack trace is appended to existing one throw tiex.InnerException ; } -------------------- ### \#6楼 ### *Nobody has explained the difference between `ExceptionDispatchInfo.Capture( ex ).Throw()` and a plain `throw` , so here it is.* **没有人能解释`ExceptionDispatchInfo.Capture( ex ).Throw()`和普通`throw`之间的区别,所以就在这里。** *The complete way to rethrow a caught exception is to use `ExceptionDispatchInfo.Capture( ex ).Throw()` (only available from .Net 4.5).* **抛出异常的完整方法是使用`ExceptionDispatchInfo.Capture( ex ).Throw()` (仅适用于.Net 4.5)。** *Below there are the cases necessary to test this:* **以下是一些必要的测试案例:** *1.* **1。** void CallingMethod() { //try { throw new Exception( "TEST" ); } //catch { // throw; } } *2.* **2。** void CallingMethod() { try { throw new Exception( "TEST" ); } catch( Exception ex ) { ExceptionDispatchInfo.Capture( ex ).Throw(); throw; // So the compiler doesn't complain about methods which don't either return or throw. } } *3.* **3。** void CallingMethod() { try { throw new Exception( "TEST" ); } catch { throw; } } *4.* **4。** void CallingMethod() { try { throw new Exception( "TEST" ); } catch( Exception ex ) { throw new Exception( "RETHROW", ex ); } } *Case 1 and case 2 will give you a stack trace where the source code line number for the `CallingMethod` method is the line number of the `throw new Exception( "TEST" )` line.* **情况1和情况2将为您提供堆栈跟踪,其中`CallingMethod`方法的源代码行号是`throw new Exception( "TEST" )`行的行号。** *However, case 3 will give you a stack trace where the source code line number for the `CallingMethod` method is the line number of the `throw` call.* **但是,情况3将为您提供堆栈跟踪,其中`CallingMethod`方法的源代码行号是`throw`调用的行号。** *This means that if the `throw new Exception( "TEST" )` line is surrounded by other operations, you have no idea at which line number the exception was actually thrown.* **这意味着,如果`throw new Exception( "TEST" )`行被其他操作包围,则您不知道实际在哪个行号上引发了异常。** *Case 4 is similar with case 2 because the line number of the original exception is preserved, but is not a real rethrow because it changes the type of the original exception.* **情况4与情况2类似,因为保留了原始异常的行号,但不是真正的重新抛出,因为它更改了原始异常的类型。** [How to rethrow InnerException without losing stack trace in C]: https://oldbug.net/q/eVx/How-to-rethrow-InnerException-without-losing-stack-trace-in-C [https_stackoom.com_question_eVx_C-_InnerException]: https://stackoom.com/question/eVx/%E5%A6%82%E4%BD%95%E5%9C%A8%E4%B8%8D%E4%B8%A2%E5%A4%B1C-%E4%B8%AD%E7%9A%84%E5%A0%86%E6%A0%88%E8%B7%9F%E8%B8%AA%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E6%8A%9B%E5%87%BAInnerException [ExceptionDispatchInfo]: http://msdn.microsoft.com/en-us/library/system.runtime.exceptionservices.exceptiondispatchinfo.aspx
相关 如何在不丢失数据的情况下迁移实时网站 在本指南中,我们将讨论如何将实时网站迁移到新的基础设施,而无需停机且不会丢失数据。 网站正在迁移 在此示例中,我们假设我们正在处理一个繁忙的电子商务网站。该电子商务网站 ╰半橙微兮°/ 2023年10月13日 21:52/ 0 赞/ 32 阅读
相关 java抛出异常的几种情况 1. 编译错误 //代码1 public static void test() throws Exception { ╰半橙微兮°/ 2023年10月10日 10:31/ 0 赞/ 33 阅读
相关 如何在不学习的情况下做到不挂科? 不学习并不能保证不挂科,学习是获得知识和提高成绩的基础。然而,如果你想试图在不学习的情况下不挂科,你可以尝试以下方法: 1. 制定计划:在考试前,为你要参加的每门考试制定一 迷南。/ 2023年10月08日 20:13/ 0 赞/ 41 阅读
相关 java内部异常堆栈跟踪,在java中重新抛出异常时,不会完全维护堆栈跟踪 本问题已经有最佳答案,请猛点这里访问。 当异常在下面的代码中重新引发时,原始堆栈跟踪不会保留。 在第148行和第150行中引发异常。重新刷新后,第150行是指定的异常源。 柔情只为你懂/ 2023年01月13日 09:22/ 0 赞/ 156 阅读
相关 如何在不丢失C#中的堆栈跟踪的情况下抛出InnerException? 本文翻译自:[How to rethrow InnerException without losing stack trace in C\?][How to rethrow I ﹏ヽ暗。殇╰゛Y/ 2022年11月28日 10:52/ 0 赞/ 129 阅读
相关 如何在不等待的情况下安全地在C#中调用异步方法 本文翻译自:[How to safely call an async method in C\ without await][How to safely call an asy Bertha 。/ 2022年11月27日 12:08/ 0 赞/ 187 阅读
相关 android 打印java堆栈_关于Java / Android:Java / Android – 如何打印出完整的堆栈跟踪?... 在Android(Java)中,如何打印出完整的堆栈跟踪? 如果我的应用程序从nullPointerException或其他东西崩溃,它会打印出一个(几乎)完整的堆栈跟踪,如下 悠悠/ 2022年10月22日 12:51/ 0 赞/ 120 阅读
相关 堆栈信息不打印的情况下如何定位报错原因 不知道小伙伴们有没有遇见过这种问题,即linux环境jar包执行时,执行到某一行后,后面的代码不再执行,log日志中也没有打印错误信息(try-cat堆栈信息被吃掉)。此时该怎 柔情只为你懂/ 2022年10月15日 03:00/ 0 赞/ 203 阅读
相关 解决Java抛出的异常,log中不含具体的堆栈信息 最近,在做项目的时候,遇到一个问题,抛了exception异常,但是定位到log的时候却发现log信息打印不全,并不能根据异常定位到具体的位置。 解决方法:配置JVM参数 - 雨点打透心脏的1/2处/ 2022年06月09日 07:21/ 0 赞/ 253 阅读
还没有评论,来说两句吧...