IDプロセスによって指定されたメイン(のみ)スレッドIDを見つけるのを手伝ってもらえますか?
タスクコンテキスト:実行中のプロセスには(現時点では)ウィンドウはありませんが、(いくつかの)スレッドがあります。
募集:WM_QUIT
メインスレッドでのみ投稿。
不要:非プライマリスレッドの使用TerminateProcess
または投稿。WM_QUIT
IDプロセスによって指定されたメイン(のみ)スレッドIDを見つけるのを手伝ってもらえますか?
タスクコンテキスト:実行中のプロセスには(現時点では)ウィンドウはありませんが、(いくつかの)スレッドがあります。
募集:WM_QUIT
メインスレッドでのみ投稿。
不要:非プライマリスレッドの使用TerminateProcess
または投稿。WM_QUIT
メインスレッドのスレッドIDを取得するためのはるかに簡単で確実な方法は、メインスレッドが独自のスレッドIDを::GetCurrentThreadId()
共有グローバル変数に記録するようにすることです。おそらく、WinMainまたは「メインスレッド」の最初のどこかにあります。
MainThreadId_G = ::GetCurrentThreadId();
次に、他のスレッドで、次のように呼び出すことができます。::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);
#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);
}
これが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()
必要がない場合は電話を削除します(私のアプリケーションではそれらが必要でした)
関数ではなく、cppファイルの先頭でこれを使用します。
DWORD mainThreadID = ::GetCurrentThreadId();
これにより、メイン関数が実行される前にmainThreadIDが初期化され、メインスレッドであることが保証されます。
特定のスレッドにメッセージを投稿することはできません。メッセージはキューに入れられ、メインスレッドからのみ処理されます。
UIを備えたWindowsプロセスを閉じる場合は、sendmessageを使用してwm_closeを別のプロセスに送信する方法を確認してください。
この関数を探しますか:
DWORD WINAPI GetProcessIdOfThreadId(_In_ DWORD ThreadId)
{
HANDLE Thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, ThreadId);
DWORD process_id = GetProcessIdOfThread(Thread);
CloseHandle(Thread);
return process_id;
}