2010-12-04 38 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]爲好,等...)