请问您能帮我找到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