轉自:Visual Studio調試器指南---多線程應用程序調試(一) - 活着的蟲子 - 博客園 (cnblogs.com)
很好入門帖;微軟那個講多線程的帖子沒看太明白,放在這里了: 調試多線程應用 - Visual Studio (Windows) | Microsoft Docs
Visual Studio調試器指南---多線程應用程序調試(一)
線程是操作系統向其授予處理器時間的指令序列。 在操作系統中運行的每個進程都包含至少一個線程。 包含多個線程的進程稱為多線程。有多個處理器、多核處理器或超線程進程的計算機可以同時運行多個線程。 使用多個線程的並行處理可以極大地提高程序性能,但也可能導致調試變得更加困難,因為正在跟蹤多個線程。
多線程處理可能會引入新類型的潛在 bug。 例如,兩個或多個線程可能需要訪問同一資源,但是一次只能有一個線程可以安全地訪問該資源。 需要某種形式的互斥才能確保每次只有一個線程訪問該資源。 如果未正確實現互斥,則可能會創建不會執行任何線程的死鎖情況。 死鎖通常是一個難以調試的問題。
用於調試多線程應用的工具
Visual Studio 提供不同的工具用於調試多線程應用程序。
-
對於線程,調試線程的主要工具有 "線程" 窗口、源窗口中的線程標記、"並行堆棧" 窗口、"並行監視" 窗口和 "調試位置" 工具欄。
-
對於使用任務並行庫(TPL)或並發運行時的代碼,用於調試的主要工具是 "並行堆棧" 窗口、"並行監視" 窗口和 "任務" 窗口,該窗口還支持JavaScript.
-
對於調試 GPU 上的線程,主要工具是“GPU 線程”窗口。
-
對於進程,主要工具是“附加到進程”對話框、“進程”窗口和“調試位置”工具欄。
Visual Studio 還提供功能強大的斷點和跟蹤點,在調試多線程應用程序時,這會很有用。 使用斷點條件和篩選器將斷點置於單個線程上。 使用跟蹤點可以在不中斷的情況下跟蹤程序的執行,從而研究死鎖之類的問題。
調試具有用戶界面的多線程應用程序可能會特別困難。 可以考慮在另一台計算機上運行應用程序並使用遠程調試。
使用 "線程" 窗口調試多線程應用
多個 Visual Studio 用戶界面元素可幫助調試多線程應用。 下面介紹 "代碼編輯器" 窗口、"調試位置" 工具欄和 "線程" 窗口中的多線程調試功能。
“啟動調試”
-
在
代碼
行上設置斷點,方法是單擊左側的滾動條線,或選擇線條並按F9。斷點在代碼行旁邊的左側滾動條中顯示為紅色圓圈。 -
選擇 "調試" > "開始調試",或按F5。
應用程序在調試模式下啟動,並在斷點處暫停。
-
在中斷模式下,通過選擇 "調試" > Windows > 線程打開 "線程" 窗口。 你必須在調試會話中才能打開或查看線程和其他調試窗口。
檢查線程標記
-
"線程" 窗口中右鍵單擊,然后選擇菜單中的 "在源中
。
源代碼行旁邊的裝訂線現在顯示一個線程標記圖標
。 線程標記指示線程在此位置停止。 如果該位置有多個已停止的線程,則會顯示
圖標。
-
將指針懸停在線程標記上。 顯示數據提示,並顯示已停止的線程或線程的名稱和線程 ID 號。 線程名稱可能
<No Name>
。為了幫助識別不需要的線程,您可以在 "線程" 窗口中重命名它們。 右鍵單擊該線程,然后選擇 "重命名"。
-
右鍵單擊源代碼中的線程標記可查看快捷菜單上的可用選項。
標記線程和取消標記線程
您可以標記線程以跟蹤您要特別注意的線程。
在源代碼編輯器或 "線程" 窗口中標記和取消標記線程。 從 "調試位置" 或 "線程" 窗口工具欄中選擇是僅顯示標記的線程還是顯示所有線程。 從任何位置進行的選擇將影響所有位置。
在源代碼中標記和取消標記線程
-
通過選擇 "視圖" > 工具欄 > 調試位置,打開 "調試位置" 工具欄。 還可以在工具欄區域中右鍵單擊,然后選擇 "調試位置"。
-
"調試位置" 工具欄有三個字段: "進程"、"線程" 和 "堆棧幀"。 下拉線程列表,並記下有多少線程。 在線程列表中,當前正在執行的線程由 > 符號標記。
-
在源代碼窗口中,將鼠標懸停在滾動條中的一個線程標記圖標上,並在數據提示中選擇標志圖標(或一個空標志圖標)。 標志圖標變為紅色。
您還可以右鍵單擊線程標記圖標,指向 "標志",然后從快捷菜單中選擇要標記的線程。
-
在 "調試位置" 工具欄上,選擇 "僅顯示標記的線程" 圖標在 "線程" 字段的右側
。 除非標記一個或多個線程,否則圖標為灰顯。
只有已標記的線程才會出現在工具欄的 "線程" 下拉列表中。 若要再次顯示所有線程,請再次選擇 "僅顯示標記的線程" 圖標。
提示
標記了某些線程后,可以將光標放在代碼編輯器中,右鍵單擊,然后選擇 "將標記的線程運行到光標處"。 請確保選擇所有已標記的線程將達到的代碼。 將標記的線程運行到光標處將暫停選定代碼行上的線程,從而可以更輕松地通過凍結和解凍線程控制執行順序。
-
若要切換當前正在執行的線程的已標記或未標記狀態,請選擇 "僅顯示標記的線程" 按鈕左側的單個標志 "切換當前線程標記狀態" 工具欄按鈕。 標記當前線程對於僅顯示標記的線程時查找當前線程非常有用。
-
若要取消標記線程,請將鼠標懸停在源代碼中的線程標記上,並選擇紅色標記圖標以清除它,或右鍵單擊線程標記,然后選擇 "取消標記"。
在 "線程" 窗口中標記和取消標記線程
在 "線程" 窗口中,已標記的線程旁邊顯示紅色標志圖標,而未標記的線程(如果已顯示)具有空圖標。
選擇標記圖標,以根據其當前狀態將線程狀態更改為標記或未標記。
還可以右鍵單擊行,然后從快捷菜單中選擇 "標記"、"取消標記" 或 "取消標記所有線程"。
"線程" 窗口工具欄還具有 "僅顯示標記的線程" 按鈕,它是兩個標志圖標中的 righthand。 它的工作方式與 "調試位置" 工具欄上的按鈕相同,其中的一個按鈕控制兩個位置的顯示。
其他線程窗口功能
在 "線程" 窗口中,選擇任意列的標頭以按該列對線程進行排序。 再次選擇以反轉排序順序。 如果顯示了所有線程,則選擇標志圖標列會按標記或未標記的狀態對線程進行排序。
"線程" 窗口的第二列(沒有標頭)是當前線程列。 此列中的黃色箭頭標記當前執行點。
"位置" 列顯示每個線程在源代碼中出現的位置。 選擇Location項旁邊的展開箭頭,或將鼠標懸停在該項上,以顯示該線程的部分調用堆棧。
有關線程調用堆棧的圖形視圖,請使用 "並行堆棧" 窗口。 若要在調試時打開窗口,請選擇 "調試"> Windows > "並行堆棧"。
除了標記 、取消標記和取消標記所有線程外,線程窗口項的右鍵單擊上下文菜單還具有:
- "在源中顯示線程" 按鈕。
- 十六進制顯示,將 "線程" 窗口中的線程 ID更改為十進制格式。
- 切換到線程,這會立即將執行切換到該線程。
- 重命名,使你可以更改線程名稱。
- 凍結和解凍命令。
凍結和解凍線程執行
可以凍結和解凍線程,也可以掛起和恢復線程,以控制線程執行工作的順序。 凍結和解凍線程可幫助解決並發性問題,如死鎖和爭用條件。
提示
若要在不凍結其他線程的情況下跟蹤單個線程,這也是一種常見的調試方案,請參閱開始調試多線程應用程序。
凍結和解凍線程:
-
在 "線程" 窗口中,右鍵單擊任意線程,然后選擇 "凍結"。 "當前線程" 列中的暫停圖標指示線程已凍結。
-
選擇 "線程" 窗口工具欄中的列,然后選擇 "掛起的計數" 以顯示 "掛起的計數" 列。 凍結線程的掛起計數值為1。
-
右鍵單擊凍結的線程,然后選擇 "解凍"。
暫停圖標消失,"掛起的計數" 值更改為0。
切換到另一個線程
嘗試切換到另一個線程時,可能會看到應用程序處於中斷模式窗口。 此窗口告訴您該線程沒有當前調試器可以顯示的任何代碼。 例如,你可能正在調試托管代碼,但線程是本機代碼。 此窗口提供了解決此問題的建議。
切換到另一個線程:
-
在 "線程" 窗口中,記下當前線程 ID (當前線程列中帶有黃色箭頭的線程)。 你需要切換回此線程以繼續運行你的應用程序。
-
右鍵單擊其他線程,然后從上下文菜單中選擇 "切換到線程"。
-
觀察 "線程" 窗口中的黃色箭頭位置是否已更改。 原始的當前線程標記也保留為輪廓。
查看代碼源編輯器中的線程標記上的工具提示,以及 "調試位置" 工具欄上的 "線程" 下拉列表中的列表。 觀察當前線程是否也已更改。
-
在 "調試位置" 工具欄上,從 "線程" 列表中選擇一個不同的線程。 請注意,當前線程還會在其他兩個位置發生更改。
-
在源代碼編輯器中,右鍵單擊線程標記,指向 "切換到線程",然后從列表中選擇另一個線程。 觀察當前線程是否在所有三個位置發生了更改。
在源代碼中,通過線程標記,只能切換到在該位置停止的線程。 使用“線程”窗口和“調試位置”工具欄可以切換到任何線程。
你現在已經了解了調試多線程應用程序的基礎知識。 您可以使用 "線程" 窗口、"調試位置" 工具欄中的 "線程" 或 "源代碼編輯器" 中的 "線程" 標記來觀察、標記和取消標記線程,以及凍結和解凍線程。