使用“並行堆棧”窗口:“線程”視圖
在“調試”菜單上,單擊“啟動調試”。 等待命中第一個斷點。
查看一個線程的調用堆棧
-
在“調試”菜單上指向“窗口”,然后單擊“線程”。 將“線程”窗口停靠在 Visual Studio 底部。
-
在“調試”菜單上指向“窗口”,然后單擊“調用堆棧”。 將“調用堆棧”窗口停靠在 Visual Studio 底部。
-
在“線程”窗口中雙擊線程,使其作為當前線程。 當前線程具有一個黃色箭頭。 更改當前線程時,其調用堆棧顯示在“調用堆棧”窗口中。
查看“並行堆棧”窗口
-
在“調試”菜單上指向“窗口”,然后單擊“並行堆棧”。 確保在左上角的框中選擇了“線程”。
通過使用 "並行堆棧" 窗口,您可以在一個視圖中同時查看多個調用堆棧。 下圖顯示了 "調用堆棧" 窗口上方的 "並行堆棧" 窗口。
主線程的調用堆棧顯示在一個框中,其他四個線程的調用堆棧則划分到另一個框中。 將這四個線程划分在一起是因為其堆棧幀共享相同的方法上下文;也就是說,它們處於相同的方法中:
A
、B
和C
。 若要查看共享同一框的線程的 Id 和名稱,請將鼠標懸停在帶有標題的框上(4 個線程)。 當前線程以粗體顯示。黃色箭頭指示當前線程的活動堆棧幀。
通過右鍵單擊“調用堆棧”窗口,可以設置要顯示堆棧幀的多少詳細信息(“模塊名稱”、“參數類型”、“參數名稱”、“參數值”、“行號”和“字節偏移量”)。
方框周圍的藍色突出顯示指示當前線程是該框的一部分。 工具提示中的粗體堆棧幀也可指示當前線程。 如果雙擊“線程”窗口中的主線程,可以看到“並行堆棧”窗口中的藍色突出顯示內容相應移動。
繼續執行到第二個斷點
-
若要繼續執行到命中第二個斷點,請在“調試”菜單上單擊“繼續”。 下圖所示為第二個斷點處的線程樹。
在第一個斷點處,所有四個線程均從 S.A 執行到 S.B 再到 S.C 方法。 該信息仍會顯示在“並行堆棧”窗口中,但是這四個線程已進一步執行。 其中一個線程繼續執行到 S.D 再到 S.E。 另一個線程繼續執行到 S.F、S.G 和 S.H。 其余兩個線程繼續執行到 S.I 和 S.J,其中一個線程從此方法執行到 S.K,而另一個線程繼續執行到非用戶外部代碼。
可以將鼠標指針懸停在框標題(例如,“1 個線程”或“2 個線程”)上,以查看線程的線程 ID。 將鼠標指針懸停在堆棧幀上可以查看線程 ID 和其他幀詳細信息。 藍色突出顯示指示當前線程,黃色箭頭指示當前線程的活動堆棧幀。
軟線程圖標(interweaved lines)指示非當前線程的活動堆棧幀。 在“調用堆棧”窗口中,雙擊 S.B 可以切換幀。 “並行堆棧”窗口通過使用綠色的曲線箭頭圖標指示當前線程的當前堆棧幀。
在“線程”窗口中進行線程切換時,“並行堆棧”窗口中的視圖相應更新。
可通過在“並行堆棧”窗口中使用快捷菜單來切換到其他線程或其他線程的其他幀。 例如,右鍵單擊 S.J,指向“切換到幀”,然后單擊某一命令。
右鍵單擊 S.C,指向“切換到幀”。 其中一個帶有選中標記的命令指示當前線程的堆棧幀。 您可以切換到相同線程的上述幀(將僅移動綠色箭頭),也可以切換到其他線程(將同時移動藍色突出顯示)。 下圖所示為子菜單。
當方法上下文只與一個堆棧幀關聯時,框標題顯示“1 個線程”,雙擊它即可切換到該線程。 如果雙擊關聯有一個以上的幀的方法上下文,則會自動彈出該菜單。 將鼠標指針懸停在方法上下文上時,請注意右側的黑色三角形。 單擊該三角形也可以顯示該快捷菜單。
對於具有多個線程的大型應用程序,您可能只希望關注某個線程子集。 “並行堆棧”窗口可僅顯示已標記線程的調用堆棧。 若要標記線程,請使用快捷菜單或線程的第一個單元格。
在工具欄上,單擊列表框旁邊的“僅顯示已標記項”按鈕。
現在,只有已標記的線程才會顯示在 "並行堆棧" 窗口中。
繼續執行到第三個斷點
-
若要繼續執行到命中第三個斷點,請在“調試”菜單上單擊“繼續”。
如果有多個線程位於同一方法中,但該方法不在調用堆棧開頭,則會在不同框中顯示該方法。 當前斷點處的一個示例是 S.L,它包含三個線程並在三個框中顯示這三個線程。 雙擊 S.L。
請注意,S.L 在其他兩個框中為粗體,這樣您可以看到 S.L 的其他顯示位置。 如果希望查看對 S.L 進行調用的幀和 S.L 所調用的幀,請單擊工具欄上的“切換方法視圖”按鈕。 下圖顯示了 "並行堆棧" 窗口的 "方法" 視圖。
請注意以上關系圖以所選方法為中心並將其單獨放在視圖中間的方框中。 被調用方和調用方分別顯示在頂部和底部。 再次單擊“切換方法視圖”按鈕可以退出該模式。
“並行堆棧”窗口的快捷菜單還包括以下其他項。
-
“十六進制顯示”,用於在十進制和十六進制之間切換工具提示中的數字。
-
符號設置打開各自的對話框。
-
在源中顯示線程在源代碼中切換線程標記的顯示,這些線程標記顯示源代碼中的線程位置。
-
“顯示外部代碼”,用於顯示所有幀(即使這些幀未處於用戶代碼中)。 使用此項可查看展開的關系圖,其中包含其他幀(這些幀可能因沒有相應符號而灰顯)。
-
-
在“並行堆棧”窗口中,確保已啟用工具欄上的“自動滾動到當前堆棧幀”按鈕。
如果關系圖較大,當單步執行到下一斷點時,您可能希望視圖自動滾動到當前線程的活動堆棧幀;即第一個命中該斷點的線程。
-
繼續之前,請在“並行堆棧”窗口中一直滾動到左側和底部。
繼續執行到第四個斷點
-
若要繼續執行到命中第四個斷點,請在“調試”菜單上單擊“繼續”。
請注意視圖如何自動滾動到位。 在“線程”窗口中切換線程或在“調用堆棧”窗口中切換堆棧幀,並注意視圖如何一直自動滾動到正確的幀。 禁用“自動滾動到當前工具幀”選項並查看不同之處。
“鳥瞰圖”還有助於在“並行堆棧”窗口中處理大型關系圖。 默認情況下,鳥瞰圖為 on。 但是,您可以通過單擊窗口右下角滾動條之間的按鈕來對其進行切換,如下圖所示。
在鳥瞰視圖中,你可以移動矩形以便在關系圖中快速平移。
朝任意方向移動此關系圖的另一種方法是:單擊此關系圖的空白區域並將其拖動到所需位置。
若要放大和縮小此關系圖,請按住 Ctrl 並移動鼠標滾輪。 或者,也可以單擊工具欄上的“縮放”按鈕並使用縮放工具。
通過單擊“工具”菜單和“選項”,並選中或清除“調試”節點下的相應選項,還可以按從上到下(而不是從下到上)的方向查看堆棧。
-
繼續之前,請在“調試”菜單上單擊“停止調試”以結束執行。
使用“並行任務”窗口和“並行堆棧”窗口的任務視圖
繼續之前,建議您先完成前面的過程。
重新啟動應用程序,直到命中第一個斷點
-
在“調試”菜單上,單擊“啟動調試”並等待命中第一個斷點。
-
在“調試”菜單上指向“窗口”,然后單擊“線程”。 將“線程”窗口停靠在 Visual Studio 底部。
-
在“調試”菜單上指向“窗口”,然后單擊“調用堆棧”。 將“調用堆棧”窗口停靠在 Visual Studio 底部。
-
在“線程”窗口中雙擊線程,以將其作為當前線程。 當前線程具有一個黃色箭頭。 更改當前線程時,將更新其他窗口。 接着,我們將查看任務。
-
在 "調試" 菜單上,指向 "窗口",再單擊 "任務"。 下圖顯示了 "任務" 窗口。
對於運行的每一項任務,您可以讀取其 ID(由名稱相同的屬性返回)、運行該任務的線程的 ID 和名稱以及任務位置(懸停以顯示具有整個調用堆棧的工具提示)。 此外,“任務”列下還會顯示傳遞到任務中的方法,即起始點。
可以對任何列進行排序。 請注意指示排序列和方向的排序標志符號。 您還可以通過向左或向右拖動列來對列重新排序。
黃色箭頭指示當前任務。 通過雙擊某一任務或使用快捷菜單可以切換任務。 切換任務時,基礎線程即成為當前線程並更新其他窗口。
在不同任務之間進行手動切換時,黃色箭頭將相應移動,而白色箭頭仍顯示導致調試器中斷的任務。
繼續執行到第二個斷點
-
若要繼續執行到命中第二個斷點,請在“調試”菜單上單擊“繼續”。
之前,"狀態" 列將所有任務顯示為 "活動",但現在兩個任務被阻止。 任務可能因多種不同原因而被阻止。 在“狀態”列中,將鼠標指針懸停在正在等待的任務上可以查看其阻止原因。 例如,在下圖中,任務 3 正在等待任務 4。
任務 4 又在等待分配給任務 2 的線程所擁有的監視器。 (右鍵單擊標題行,然后選擇 "列" > 線程分配查看任務2的線程分配值 ")。
可以通過單擊 "任務" 窗口第一列中的標志來標記任務。
使用標記功能可以跟蹤同一調試會話中的不同斷點之間的任務或篩選“並行堆棧”窗口中顯示的調用堆棧所對應的任務。
在先前使用“並行堆棧”窗口時,已查看了應用程序線程。 請再次查看“並行堆棧”窗口,但這次查看應用程序任務。 請在左上方的框中選擇“任務”來執行此操作。 下圖所示為任務視圖。
當前未在執行任務的線程不會顯示在“並行堆棧”窗口的任務視圖中。 此外,對於執行任務的線程,某些與任務無關的堆棧幀將從堆棧的頂部和底部篩選掉。
再次查看 "任務" 窗口。 右擊任何列標題可以查看該列的快捷菜單。
您可以使用此快捷菜單添加或移除列。 例如,AppDomain 列未處於選中狀態;因此,不會在列表中顯示它。 單擊“父級”。 此時將顯示“父級”列,但不顯示四個任務中任何任務的值。
繼續執行到第三個斷點
-
若要繼續執行到命中第三個斷點,請在“調試”菜單上單擊“繼續”。
此時,新任務(即任務 5)正在運行,而任務 4 則處於等待狀態。 通過將鼠標指針懸停在“狀態”窗口中正在等待的任務上,可以查看其原因。 請注意,父列中的任務4是任務5的父項。
若要更好地直觀顯示父子關系,請右鍵單擊列標題行,然后單擊 "父子視圖"。 您應看到以下圖示。
請注意,任務4和任務5正在同一線程上運行(如果它是隱藏的,則顯示 "線程分配" 列)。 此信息不會顯示在 "線程" 窗口中;這里看到的是 "任務" 窗口的另一個優點。 為確認這一點,請查看“並行堆棧”窗口。 確保你正在查看“任務”。 在任務窗口中雙擊任務4和5。 執行此操作時,“並行堆棧”窗口中的藍色突出顯示內容隨之更新。 此外,還可以通過掃描“並行堆棧”窗口上的工具提示來查找任務 4 和任務 5。
在“並行堆棧”窗口中右鍵單擊 S.P,然后單擊“轉到線程”。 此時,窗口將切換到線程視圖,並顯示相應幀。 你可以在同一線程上查看兩個任務。
這是“並行堆棧”窗口中的任務視圖相較於“線程”窗口的另一優勢。
繼續執行到第四個斷點
若要繼續執行到命中第三個斷點,請在“調試”菜單上單擊“繼續”。 單擊要按 ID 排序的“ID”列標題。 您應看到以下圖示。
由於任務 5 已完成,因此不再顯示該任務。 如果計算機上並非如此並且未顯示死鎖,請通過按“F11”單步執行一次。
任務3和任務4現在正在等待,並被阻止。 此外,還存在 5 個作為任務 2 的子級的新任務,目前已計划這些任務。 已計划任務是已在代碼中啟動但尚未運行的任務。 因此,其“位置”和“線程分配”列為空。
再次查看“並行堆棧”窗口。 每個框的標題都具有一個顯示線程 ID 和名稱的工具提示。 在“並行堆棧”窗口中切換到任務視圖。 將鼠標指針懸停在標題上可以查看任務 ID 和名稱以及任務狀態,如下圖所示。
可以按列對任務進行分組。 在 "任務" 窗口中,右鍵單擊 "狀態" 列標題,然后單擊 "按狀態分組"。 下圖顯示按狀態分組的 "任務" 窗口。
此外,還可以按其他列進行分組。 通過對任務進行分組,你可以關注某個任務子集。 每個可折疊的組都包含一個分組在一起的項的計數。
要檢查的任務窗口的最后一項功能是右鍵單擊任務時顯示的快捷菜單。
快捷菜單根據任務狀態顯示不同的命令。 這些命令可能包括“復制”、“全選”、“十六進制顯示”、“切換到任務”、“凍結指定的線程”、“凍結此線程之外的全部線程”、“解凍指定的線程”和“標志”。
你可以凍結一個或多個任務的基礎線程,也可以凍結除指定線程外的所有線程。 凍結的線程在 "任務" 窗口中以 "線程" 窗口中的藍色暫停圖標表示。