請問您能幫我找到ID進程給定的主(唯一)線程ID嗎?如何獲取進程的主線程標識(由其ID標識)?
任務上下文: 正在運行的進程(此刻)沒有窗口,而是(某些)線程。
通緝: 僅在主線程中發佈WM_QUIT
。
不想要的: 在非主線程使用TerminateProcess
或發佈WM_QUIT
。
請問您能幫我找到ID進程給定的主(唯一)線程ID嗎?如何獲取進程的主線程標識(由其ID標識)?
任務上下文: 正在運行的進程(此刻)沒有窗口,而是(某些)線程。
通緝: 僅在主線程中發佈WM_QUIT
。
不想要的: 在非主線程使用TerminateProcess
或發佈WM_QUIT
。
#ifndef MAKEULONGLONG
#define MAKEULONGLONG(ldw, hdw) ((ULONGLONG(hdw) << 32) | ((ldw) & 0xFFFFFFFF))
#endif
#ifndef MAXULONGLONG
#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0))
#endif
bool CloseProcessMainThread(DWORD dwProcID)
{
DWORD dwMainThreadID = 0;
ULONGLONG ullMinCreateTime = MAXULONGLONG;
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap != INVALID_HANDLE_VALUE) {
THREADENTRY32 th32;
th32.dwSize = sizeof(THREADENTRY32);
BOOL bOK = TRUE;
for (bOK = Thread32First(hThreadSnap, &th32); bOK;
bOK = Thread32Next(hThreadSnap, &th32)) {
if (th32.th32OwnerProcessID == dwProcID) {
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION,
TRUE, th32.th32ThreadID);
if (hThread) {
FILETIME afTimes[4] = {0};
if (GetThreadTimes(hThread,
&afTimes[0], &afTimes[1], &afTimes[2], &afTimes[3])) {
ULONGLONG ullTest = MAKEULONGLONG(afTimes[0].dwLowDateTime,
afTimes[0].dwHighDateTime);
if (ullTest && ullTest < ullMinCreateTime) {
ullMinCreateTime = ullTest;
dwMainThreadID = th32.th32ThreadID; // let it be main... :)
}
}
CloseHandle(hThread);
}
}
}
#ifndef UNDER_CE
CloseHandle(hThreadSnap);
#else
CloseToolhelp32Snapshot(hThreadSnap);
#endif
}
if (dwMainThreadID) {
PostThreadMessage(dwMainThreadID, WM_QUIT, 0, 0); // close your eyes...
}
return (0 != dwMainThreadID);
}
您不能發佈消息到特定的線程。消息放入隊列中,並僅從主線程處理。
如果你想關閉窗口的過程,具有UI,看看using sendmessage to send wm_close to another process
謝謝您的回覆,我將標誌着你的答案一樣有用。 – 2013-03-24 10:11:44
實際上,可以有多個消息隊列,每個消息隊列都與不同的線程關聯,如果存在,您可以使用PostThreadMessage將消息發送到特定的線程。 – 2013-03-24 20:43:38
@哈里:知道這很有趣!當存在多個隊列時,現實的用例是什麼? – alex 2013-03-25 06:46:58
一個更簡單和更可靠的方式來獲得主線程的線程ID是讓主線程記錄其
MainThreadId_G = ::GetCurrentThreadId();
然後在其他線程,您可以撥打:使用::GetCurrentThreadId()
到一個共享的全局變量,也許在你的WinMain或在某處你的「主線程」的開始自己的線程ID ::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);
我絕對喜歡這個答案。簡潔,提供完整的答案,並有一個很好的解釋。當然,可以在創建時將主線程ID作爲參數傳遞給工作線程,而不是使用全局變量。 – 2015-11-04 11:15:02
我檢查了這是如何MFC處理,看起來UI線程從構造函數確定:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc\appcore.cpp:
CWinApp::CWinApp(LPCTSTR lpszAppName)
{
...
m_nThreadID = ::GetCurrentThreadId();
而且使用MFC調用AfxGetApp()->m_nThreadID
你能弄清楚UI線程ID。
但是,如果.dll不是從主線程加載的,那麼即使MFC的方法不起作用,此方法也不起作用AfxGetApp()->m_nThreadID
將返回除主線程外的其他內容。
但是,通常您的.dll會從主線程加載,但您的.dll不是必需的mfc啓用。我有可以推薦的做法是這樣的:
class GetMainThread
{
public:
GetMainThread()
{
m_nThreadID = ::GetCurrentThreadId();
}
DWORD m_nThreadID;
}getMainThread;
DWORD getUIThread()
{
DWORD id = 0;
if(AfxGetApp() != NULL)
id = AfxGetApp()->m_nThreadID;
else
id = getMainThread.m_nThreadID;
return id;
} //getUIThread
如果.dll文件由主UI線程加載,你會得到從構造函數調用(GetMainThread類)正確線程ID。如果
刪除AfxGetApp()
電話你不需要他們(在我的應用程序所需要的那些)
看起來不錯,謝謝! – 2013-03-24 10:12:40
如果它包含關於代碼的作用和工作原理的一些解釋,這個答案會更好。特別是,如果在進程有多個線程的情況下,你如何確定「主」線程是哪個進程的特定進程?它看起來像你正在創建線程的時間。這不一定是可靠的啓發式;重要的是要指出,人們可以仔細考慮這種方法的優點和缺點。包含* only *代碼的答案不是答案。 – 2013-03-24 10:56:33