2012-02-24 26 views
0

(初始內容編輯,因爲我發現這是無關緊要的).NET - 異常堆棧跟蹤線路上通用的方法,消除

我的應用程序有它包裝在 委託業務,並以往通用的RESTful HTTP客戶端我的WrapOperation方法(如下所示)。

然而,當異常被拋出堆棧跟蹤只包含一個條目:

at MyProject.Client.RestClient.WrapOperation[T](String method, String path, Object requestObject, RestOperation`1 action) in D:\{fileName}\RestClient.cs:line 196 

我已經減少了問題的代碼,只是這樣的:

private T WrapOperation<T>(String method, String path, Object requestObject, RestOperation<T> action) { 

     HttpWebRequest request; 
     RestTransaction txn = CreateRequest(method, path, requestObject, out request); 

     //////////////////////////// 

     try { 

      throw new WebException("testing stack trace 6"); 
      throw new Exception("testing stack trace 7"); 

      using(HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { 

       txn.GotResponse(response); 

       return action(txn, response); 
      } 

     } catch(WebException wex) { 
      // NOTE: When exceptions are caught, they're missing the first few entries of the stack trace 
      // And appear as though "WrapOperation[T]" (sic) is the entrypoint. Why is this? 


      if(wex.Response != null) { 

       HttpWebResponse response = (HttpWebResponse)wex.Response; 

       txn.GotResponse(wex, response); 

       CopyResponseToMemoryStream(response, txn).Dispose(); 

      } else { 

       txn.GotResponse(wex); 
      } 

      // NOTE: However, when these RestExceptions are caught (by WrapOperation's caller), their stack trace is complete and shows the entire trace 
      throw new RestException("WebExeption during GetResponse.", txn, wex); 

     } catch(Exception ex) { 

      txn.GotResponse(ex); 

      // NOTE: However, when these RestExceptions are caught (by WrapOperation's caller), their stack trace is complete and shows the entire trace 
      throw new RestException("Non-WebException during GetResponse.", txn, ex); 
     } 

    } 

當「測試堆棧跟蹤6 「拋出異常時,被捕獲(WebException wex)捕獲時,wex的堆棧跟蹤僅包含一個條目。

這是爲什麼?

+0

異常代碼的外觀如何?你正在做'拋出'還是'拋出'來傳遞鏈中的異常? – asawyer 2012-02-24 19:41:50

+0

你沒有發佈缺少的中間方法的代碼,所以很難猜測。這裏至少有兩種情況。你只會看到任務執行的方法,異常跟蹤是基於線程的。抖動優化器爲內聯小方法生成代碼,這樣您就無法看到這些代碼,異常是基於堆棧幀的。使用[MethodImpl]來抑制該優化。 – 2012-02-25 14:28:11

+0

什麼方法是你的線程的入口點?它是DoAsync(Action)?你能否展示創建,啓動和執行異步任務的代碼? – 2012-02-25 11:59:46

回答

0

看起來像是將原始異常包裝到自定義異常類中。當您讀取異常以查看堆棧跟蹤時,您還必須檢查內部異常行以獲取完整跟蹤。

編輯 -

在拋出異常的堆棧跟蹤開始,所以顯示的堆棧跟蹤是正確的,我原來問題的描述是正確的。

無論何時您拋出一個新的異常,該異常的堆棧跟蹤都會在此時開始。

在你原來的例子再次,考察這裏的內部異常:

//throwing the exception resets the stack trace! 
//the next catch will see the exception as coming from this line, and 
//will need to look at the inner exception at that point to see the 
//original exception! I Think! I have no idea what RestException is, 
//only that your passing the original exception ex into it as a parameter. 
throw new RestException("Non-WebException during GetResponse.", txn, ex); 
+0

內部異常(如RestExceptions實例化時分配的)具有初始堆棧框架丟失 - 事實上,我打包異常是無關緊要的。 – Dai 2012-02-24 20:00:53

0

如果你(未顯示)的方法之一是捕捉異常,然後重新拋出它像這樣:

throw ex; 

然後堆棧軌跡將被重置爲在重新投影點開始。

throw; 

將維護堆棧跟蹤。