2016-06-06 14 views
2

當我在我正在等待的方法的主體中設置斷點時,Visual Studio調試器將顯示沒有任何C#編譯器生成的代碼的調用堆棧。爲什麼Visual Studio調試器不顯示由await關鍵字生成的狀態機代碼?

請看下面的圖片,其中顯示了我的簡單async方法和調用堆棧。

enter image description here

注意,存在對MoveNext或初始化狀態機對象或所述TaskAwaiter<TResult>或在調用棧中的AsyncTaskOfTMethodBuilder沒有呼叫。

這是爲什麼?就像在IL Spy中一樣,Visual Studio中是否有一些設置可以切換到在調試會話進行時顯示調用堆棧和編輯器中的狀態機代碼?

我突然想起在重新編寫的按鈕單擊處理程序代碼上有一個DebuggerStepThroughAttribute實例化狀態機。但我不確定這是否是調試器隱藏的原因。難道這不應該讓調用堆棧中編譯器生成的方法的堆棧框架變灰嗎?

是不是DebuggerHiddenAttribute讓代碼對調試器不可見?

+1

你的斷點是在另一個線程上運行的任務中,爲什麼應該有創建該線程的callstack的證據?你有沒有檢查你可以在調試器中獲得的獨立線程窗口?我不記得名字,但是可以打開一個窗口/窗格,顯示程序中所有線程的狀態。 –

+0

然而,問題在於按鈕單擊事件處理程序方法暫時完成。它已經返回,這可能發生在額外線程啓動期間的第一個毫秒內,這意味着運行任務的線程的調用堆棧不會顯示按鈕事件處理程序,您正在尋找的方法最有可能已經返回。 –

回答

2

這裏有幾件事要注意。

首先,你有2個線程玩法:

  1. 主線程,運行的消息泵和擁有已在它的按鈕
  2. 正在運行任務的線程窗口

一個線程內部的調用堆棧決不會反映創建它的線程當前正在執行的操作。

如果您檢查可以在調試器中顯示所有線程及其調用堆棧的調試器窗格,您將看到兩個線程及其調用堆棧。

但是,這隻會顯示按鈕事件處理程序,如果執行此方法的線程在調試程序觸發您的斷點時仍在方法中。由於旋轉新線程的開銷,這很可能不是真的。

這樣做的原因是,async/await返回從async方法當它擊中的await。當單獨的線程開始執行委託時,按鈕事件處理程序方法最有可能返回。

即使你手工紡一個線程爲您的委託,並加入(等待)線程,你不會看到這個在調用堆棧,但你一定要看到它在其他調試器窗格中的線程和他們的調用堆棧。

+0

哦,是的。我的錯。謝謝。 –

相關問題