2009-05-25 97 views
15

如何爲Win32線程設置一個名稱。我沒有找到任何Win32 API來實現相同。基本上我想在日誌文件中添加線程名稱。 TLS(線程本地存儲)是唯一的方法嗎?如何將名稱設置爲Win32線程?

+0

的SetThreadDescription()API是:

如果你想看到這個增益更好的支持,如在WinDbg中,Visual Studio中,和崩潰轉儲文件,請使用此鏈接爲它投票,未來,微軟將支持這個API。有關詳細信息,請參閱本答案:http://stackoverflow.com/a/43787005/434413 – 2017-05-04 15:25:09

回答

1

您可以隨時將這些信息存儲在合適的數據結構中。使用散列或地圖將GetThreadId()映射到此名稱。由於GetThreadId()始終是一個唯一的標識符,所以這工作得很好。

乾杯!

當然,如果他創造了許多 線程,即HashMap的會慢慢填補 和使用越來越多的內存,所以 一些清理過程可能是一個 好事也。

你是絕對正確的。當一個線程死亡時,它在地圖中的相應條目自然應該被刪除。

+0

當然,如果他創建多個線程,即HashMap的會慢慢填滿,使用越來越多的內存,所以有些清理過程可能是一個很好的事情爲好。 – 2009-05-26 21:27:42

+0

downvoting因爲我太需要一個回答這個問題,但我真的需要一個名稱設置爲線程剖析原因。你的回答沒有回答問題:P – 2015-07-09 23:31:40

29

這有幫助嗎? How to: Set a Thread Name in Native Code

在託管代碼中,它與設置相應Thread對象的Name屬性一樣簡單。

+1

我猜它僅適用於Visual Studio調試器來顯示線程名。 – Canopus 2009-05-25 08:39:17

+1

其他調試器也紛紛效仿,並在調試器數據結構中存儲的線程名相同的信號響應 – 2011-02-13 21:46:31

+3

作爲http://thetweaker.wordpress.com/2009/04/10/naming-threads/筆記,他們都這樣做。在沒有調試器的情況下,名稱將不會被存儲,並且不能用於記錄目的。討厭的錯誤,當你嘗試調試時,它突然再次工作。 – MSalters 2011-06-27 13:29:22

17

http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.90).aspx

// 
// Usage: SetThreadName (-1, "MainThread"); 
// 
#include <windows.h> 
const DWORD MS_VC_EXCEPTION=0x406D1388; 

#pragma pack(push,8) 
typedef struct tagTHREADNAME_INFO 
{ 
    DWORD dwType; // Must be 0x1000. 
    LPCSTR szName; // Pointer to name (in user addr space). 
    DWORD dwThreadID; // Thread ID (-1=caller thread). 
    DWORD dwFlags; // Reserved for future use, must be zero. 
} THREADNAME_INFO; 
#pragma pack(pop) 

void SetThreadName(DWORD dwThreadID, char* threadName) 
{ 
    THREADNAME_INFO info; 
    info.dwType = 0x1000; 
    info.szName = threadName; 
    info.dwThreadID = dwThreadID; 
    info.dwFlags = 0; 

    __try 
    { 
     RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR),  (ULONG_PTR*)&info); 
    } 
    __except(EXCEPTION_EXECUTE_HANDLER) 
    { 
    } 
} 
9

的Win32線程沒有名稱。有一個Microsoft約定,應用程序會提出包含線程名稱的特殊SEH異常。這些異常可以被調試器攔截並用於指示線程名稱。一些答案涵蓋了這一點。

但是,這一切都由調試器處理。線程本身是無名對象。所以,如果你想把名字和你的線索聯繫起來,你必須開發自己的機制。雖然您可以使用線程本地存儲,只允許您從該線程中執行的代碼獲取名稱。所以線程ID和名稱之間的全局映射似乎是最自然和有用的方法。

1

另一種方法是在線程的TEB的ArbitraryUserPointer字段中存儲指向名稱的指針。這可以在運行時寫入和讀取。

有一個CodeProject文章標題爲"Debugging With The Thread Information Block",告訴你如何做到這一點。

3

您可以使用線程本地存儲對象來存儲名稱。例如,

__declspec(thread) char threadName[32]; 

然後,您可以從一個線程寫入並讀取它。這在記錄器應用程序中很有用,您可以在其中打印出每條消息的線程名稱。您可能想要在線程啓動時立即寫入此變量,並且還會拋出Microsoft異常(https://stackoverflow.com/a/10364541/364818),以便調試器也知道線程名稱。

2

根據與微軟調試團隊領導討論(詳見下文鏈接)的SetThreadDescription API是將要使用微軟前進,以支持線程在本機代碼正式命名的API。 「正式」是指一個MS支持的用於命名線程的API,而不是當前僅在Visual Studio中運行進程時才起作用的異常拋出黑客。

此API在Windows 10面世開始,版本1607

然而,目前很少有工具支持,所以您設置的名稱將不會在Visual Studio或WinDbg中的調試器可見。但是,到2017年4月,Microsoft xperf/WPA工具確實支持它(通過此API命名的線程將在這些工具中正確顯示其名稱)。

https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/17608120-properly-support-native-thread-naming-via-the-sett