Multithreading winapi线程在消息传递工作之前需要时间初始化?
我有一个按顺序创建线程的主程序: ThreadB那么 ThreadA(传递给ThreadB的ID) 使用CreateThread函数 线程A使用PostThreadMessage向线程B发送消息。 B使用GetMessage获取消息 我遇到的问题是,PostThreadMessage在第一次调用时会随机阻塞,并且永远不会返回,有时程序运行正常,有时运行程序,在第一次PostThreadMessage时,它会以0 CPU使用率阻塞。然而,如果我在第一条PostThreadMessage之前将Sleep(10)添加到ThreadA,我似乎从未遇到过这个问题Multithreading winapi线程在消息传递工作之前需要时间初始化?,multithreading,winapi,messages,timing,Multithreading,Winapi,Messages,Timing,我有一个按顺序创建线程的主程序: ThreadB那么 ThreadA(传递给ThreadB的ID) 使用CreateThread函数 线程A使用PostThreadMessage向线程B发送消息。 B使用GetMessage获取消息 我遇到的问题是,PostThreadMessage在第一次调用时会随机阻塞,并且永远不会返回,有时程序运行正常,有时运行程序,在第一次PostThreadMessage时,它会以0 CPU使用率阻塞。然而,如果我在第一条PostThreadMessage之前将Sle
关于线程和消息的计时,我遗漏了什么?在线程具有消息队列之前,您无法向线程发送消息。只有在该线程调用函数(如
GetMessage
或PeekMessage
)时,才会创建消息队列。睡眠所做的是将发送线程延迟足够长的时间,以便接收线程调用GetMessage
并设置其消息队列
顺便说一句,我强烈建议不要使用
PostThreadMessage
,因为这些消息可能会丢失。最好在接收线程上创建一个仅消息窗口(其父线程为HWND\u message
),然后将消息发送给该线程。在线程具有消息队列之前,不能将消息发送给该线程。只有在该线程调用函数(如GetMessage
或PeekMessage
)时,才会创建消息队列。睡眠所做的是将发送线程延迟足够长的时间,以便接收线程调用GetMessage
并设置其消息队列
顺便说一句,我强烈建议不要使用
PostThreadMessage
,因为这些消息可能会丢失。最好在接收线程上创建一个只显示消息的窗口(带有HWND\u message
)并将消息发送到该窗口。要添加到Anthony Williams的正确答案中,我用来处理此问题的代码如下所示。我有一个类似MyThread的课程
void MyThread::Start()
{
m_hResumeMain = CreateEvent(NULL,FALSE,FALSE,NULL);
m_hThread = CreateThread(NULL,0,ThreadProc,this,0,&m_dwThreadId);
WaitForSingleObject(m_hResumeMain,INFINITE);
CloseHandle(m_hResumeMain);
m_hResumeMain=0;
}
DWORD MyThread::ThreadProc(LPVOID pv)
{
MyThread* self = (MyThread*)pv;
return self->ThreadProc();
}
DWORD MyThread::ThreadProc()
{
MSG msg;
// Create the thread message queue
PeekMessage(&msg,0,0,0,PM_NOREMOVE);
// Resume the main thread
SetEvent(m_hResumeMain);
while(GetMessage(&msg,0,0,0)>0){
if(msg.hwnd){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
DoThreadMessage(&msg);
}
}
return 0;
}
问题的症结在于,您最终无法依靠
睡眠
来保证工作线程得到充分初始化。另外,一般来说,在允许启动线程恢复之前,工作线程需要完成的工作量通常很小。因此,在创建线程之前创建一个事件对象,在主线程上等待它,并在初始化完成后在工作线程上发出信号。要添加到Anthony Williams的正确答案中,我用于处理此问题的代码如下所示。我有一个类似MyThread的课程
void MyThread::Start()
{
m_hResumeMain = CreateEvent(NULL,FALSE,FALSE,NULL);
m_hThread = CreateThread(NULL,0,ThreadProc,this,0,&m_dwThreadId);
WaitForSingleObject(m_hResumeMain,INFINITE);
CloseHandle(m_hResumeMain);
m_hResumeMain=0;
}
DWORD MyThread::ThreadProc(LPVOID pv)
{
MyThread* self = (MyThread*)pv;
return self->ThreadProc();
}
DWORD MyThread::ThreadProc()
{
MSG msg;
// Create the thread message queue
PeekMessage(&msg,0,0,0,PM_NOREMOVE);
// Resume the main thread
SetEvent(m_hResumeMain);
while(GetMessage(&msg,0,0,0)>0){
if(msg.hwnd){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
DoThreadMessage(&msg);
}
}
return 0;
}
问题的症结在于,您最终无法依靠睡眠
来保证工作线程得到充分初始化。另外,一般来说,在允许启动线程恢复之前,工作线程需要完成的工作量通常很小。因此,在创建线程之前创建一个事件对象,在主线程上等待它,并在初始化完成后在工作线程上发出信号