2013-03-24 67 views

回答

6
#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); 
} 
+1

看起來不錯,謝謝! – 2013-03-24 10:12:40

+6

如果它包含關於代碼的作用和工作原理的一些解釋,這個答案會更好。特別是,如果在進程有多個線程的情況下,你如何確定「主」線程是哪個進程的特定進程?它看起來像你正在創建線程的時間。這不一定是可靠的啓發式;重要的是要指出,人們可以仔細考慮這種方法的優點和缺點。包含* only *代碼的答案不是答案。 – 2013-03-24 10:56:33

2

您不能發佈消息到特定的線程。消息放入隊列中,並僅從主線程處理。

如果你想關閉窗口的過程,具有UI,看看using sendmessage to send wm_close to another process

+0

謝謝您的回覆,我將標誌着你的答案一樣有用。 – 2013-03-24 10:11:44

+3

實際上,可以有多個消息隊列,每個消息隊列都與不同的線程關聯,如果存在,您可以使用PostThreadMessage將消息發送到特定的線程。 – 2013-03-24 20:43:38

+0

@哈里:知道這很有趣!當存在多個隊列時,現實的用例是什麼? – alex 2013-03-25 06:46:58

4

一個更簡單和更可靠的方式來獲得主線程的線程ID是讓主線程記錄其

MainThreadId_G = ::GetCurrentThreadId(); 

然後在其他線程,您可以撥打:使用::GetCurrentThreadId()到一個共享的全局變量,也許在你的WinMain或在某處你的「主線程」的開始自己的線程ID ::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);

+0

我絕對喜歡這個答案。簡潔,提供完整的答案,並有一個很好的解釋。當然,可以在創建時將主線程ID作爲參數傳遞給工作線程,而不是使用全局變量。 – 2015-11-04 11:15:02

1

我檢查了這是如何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()電話你不需要他們(在我的應用程序所需要的那些)