2010-12-04 69 views
17

以前讨论过有关重新抛出异常的正确方法。相反,这个问题是关于如何在使用rethrow时从Visual Studio中获得有用的行为。C#重新抛出异常:如何在IDE中获取异常堆栈?

考虑以下代码:

static void foo() { 
     throw new Exception("boo!"); 
    } 

    static void Main(string[] args) { 
     try { 
      foo(); 
     } catch (Exception x) { 
      // do some stuff 
      throw; 
     } 
    } 

散发出来具有正确的堆栈跟踪,显示FOO()作为该异常的源的异常。 但是,GUI调用堆栈窗口只显示Main,而我期待它显示异常的调用堆栈,直到foo。

当没有重新抛出时,我可以使用GUI非常快速地导航调用堆栈,以查看哪个调用导致异常以及我们如何到达那里。

随着rethrow我想能够做同样的事情。相反,GUI显示的调用堆栈对我没有用处。我必须将异常详细信息复制到剪贴板,将其粘贴到记事本,然后手动导航到我感兴趣的调用堆栈的任何功能。

顺便说一句,如果我添加[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]或者如果我将捕获量更改为catch (Exception)

我的问题是:鉴于我使用的代码重新抛出,有人可以建议一种方便的方式来导航与异常相关联的调用堆栈吗?我使用Visual Studio 2010中

+0

为什么要重新抛出异常?在这里没有包含`catch`子句中的更多代码吗?否则,我认为你的解决方案是简单地没有发现异常。 – 2010-12-04 01:14:50

+1

罗伯特,这是一个最小的片段来说明问题。实际的代码在重新推出之前做了一些工作。 – redtuna 2010-12-04 01:19:14

回答

11

的中断调试在throwMain因为该异常未处理。默认情况下,调试器只会处理未处理的异常。在Main停止后,异常中出现foo原始异常的调用堆栈,但所有其他上下文都已丢失(例如本地,堆栈/内存状态)。

这听起来像你想的调试器来foothrow打破,所以你应该告诉调试器在第一次机会异常打破:

  1. 调试»例外...(按Ctrl +Alt键 + Ë
  2. 检查 “时抛出” 为你关心的异常类型(在这种情况下,Commange语言运行库异常)
  3. 点击OK
  4. 开始调试

在这种情况下,调试器会立即打破时foo抛出异常。现在,您可以在原始异常的上下文中检查堆栈,本地等。如果继续执行(F5),调试器将在Main重新抛出时再次中断。

采取另一种方法,如果您运行的是VS2010 Ultimate,还可以使用IntelliTrace“向后调试”来查看异常时的参数,线程和变量。有关详细信息,请参阅this MSDN article。 (完全披露:我在一个与IntelliTrace密切相关的团队工作)。

+1

谢谢,这可以在某些情况下确实有所帮助。问题在于,就我而言,随着时间的推移会出现很多异常情况,而且我只对少数将会重新生成的东西感兴趣。查看每一个抛出的异常将会是更多的工作,就像我现在所做的那样复制/粘贴调用堆栈。我希望能够轻松地导航异常的调用堆栈,即使某些相关联的状态丢失。 – redtuna 2010-12-04 01:28:43

1

不是说你应该重新罚球,但here“SA博客中有关如何保留堆栈跟踪,基本上它归结为:

private static void PreserveStackTrace(Exception exception) 
{ 
    MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace", 
    BindingFlags.Instance | BindingFlags.NonPublic); 
    preserveStackTrace.Invoke(exception, null); 
} 

... 
catch (Exception ex) 
{ 
    // do something 
    // ... 
    PreserveStackTrace(ex); 
    throw; 
} 
+2

谢谢,但这并不能解决我的特殊问题。正如博客文章解释的那样,这段代码有助于在异常中获得正确的堆栈跟踪,这种情况下原始异常和捕获使用相同的方法。在我的情况下,异常保存了正确的堆栈跟踪:问题是我不知道如何使用GUI来导航堆栈跟踪。 – redtuna 2010-12-04 01:24:21

0

迈克失速给予了great and simple solution您的问题:

,你重新抛出异常与属性

标记方法[DebuggerNonUserCode]

IDE将考虑这是不是你的代码,并不会打破调试器这样的地方,而是看起来更进一步,显示下一次重新抛出或初始异常的地方。

(如果下次重新抛出也烦人,将其标记为[DebuggerNonUserCode]为好,等...)