其他人想必會有這樣的感覺,早上酣暢淋漓的寫完一段代碼,心情特別舒適,可是卻發現了異常,然後開始debug直到忘記了吃飯,好心情就一點點被消磨掉。這種情況在寫多線程代碼的時候更是常見,一個背景工作執行緒的任務被層層封裝,然後才被扔到背景工作執行緒隊列,我從哪裡來是不知道的,甚至於連我在哪裡都不知道,設定線程名稱,就是為瞭解決“我在哪裡”的問題。在debug時,線程有了名稱,查bug的效率會得到提升。
設定線程名稱,只有短短的幾行代碼,windows已經做好了準備,只需要觸發它。這麼簡單的東西其實沒有必要寫到部落格裡,但是最近我發現還是有不少人不知道、或者沒想到去這麼做的。
以上是廢話,以下才是重點:
#include <iostream>#include <windows.h>#include <process.h>//2013.3.5//cswuyg//參考 chromium源碼: src\base\threading\platform_thread_win.cc// The information on how to set the thread name comes from// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspxconst DWORD kVCThreadNameException = 0x406D1388;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;// This function has try handling, so it is separated out of its caller.void SetNameInternal(DWORD thread_id, const char* name){ //只在調試的時候生效 if (!::IsDebuggerPresent()) return; THREADNAME_INFO info; info.dwType = 0x1000; info.szName = name; info.dwThreadID = thread_id; info.dwFlags = 0; __try { RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD), reinterpret_cast<DWORD_PTR*>(&info)); } __except(EXCEPTION_CONTINUE_EXECUTION) { }}static unsigned int _stdcall Run(void* argv){ while(true) { std::cout << "Thread " << (int)argv << std::endl; Sleep(5000); }}void testFunc(){ DWORD thread_id_1; HANDLE thread_handle_1 = (HANDLE)_beginthreadex( NULL, 0, Run, (void*)1, 0, (unsigned int*)&thread_id_1); SetNameInternal(thread_id_1, "My Thead Thread_1"); DWORD thread_id_2; HANDLE thread_handle_2 = (HANDLE)_beginthreadex( NULL, 0, Run, (void*)2, 0, (unsigned int*)&thread_id_2); SetNameInternal(thread_id_2, "My Thead Thread_2");}int main(){ testFunc(); system("pause"); return 1;}
啥也不說了,代碼很簡單。