BOOL PostThreadMessage(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam
); 这个函数既可以发送消息给工作线程,也可以发送给UI线程
问题1:这个函数成功执行的前提是目标线程已经有了一个消息队列。否则函数会失败。 通过GetLastError()函数可以获得错误代码1444。
这个问题的解决方式有以下两个:
1 不断调用PostThreadMessage函数,直到函数成功。 这是因为当线程收到这样的函数以后,会自动创建消协队列。
2 创建Event对象,让PostThreadMessage等待目标线程创建一个消息队列。而目标线程可以通过调用PeekMessage强制系统创建一个message queue。
示例代码如下:
假设mainAPP是发送线程ThreadA是接受线程
/*mainAPP.cpp*/
……
hStartEvent = ::CreateEvent(0,FALSE,FALSE,0); //create thread start event
if(hStartEvent == 0)
{
printf("create start event failed,errno:%d\n",::GetLastError());
return 1;
}
::WaitForSingleObject(hStartEvent,INFINITE);
CloseHandle(hStartEvent);
if(!PostThreadMessage(threadaID, WM_MESSAGE_A,0,0))
{
_tprintf(_T("post error! %d\n"), GetLastError());
return 1;
}
……
ThreadA是接受线程
/* ThreadA */
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
if(!SetEvent(hStartEvent))
{
printf("set event error,%d\n",GetLastError());
return 1;
}
while(true){
if(GetMessage(&msg, 0,0,0)) {
switch(msg.message){
case WM_MESSAGE_A:
……
break;
}
}
}
}
问题2:消息不能包含大量数据。 解决如下
1 发送线程在堆中非配一个大量数据 2 消息中包含堆的指针,然后进行发送 3 目标线程序收到消息后,把发送线程序分配的堆释放。
示例程序如下:
/*构造信息如下*/
char* pInfo = new char[MAX_INFO_SIZE]; //发送线程在这里创建了一个堆
sprintf(pInfo,"msg_%d",++count);
PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0)//post thread msg
/*解释信息如下*/
if(GetMessage(&msg,0,0,0)) //get msg from message queue
{
switch(msg.message)
{
case MY_MSG:
char * pInfo = (char *)msg.wParam;
printf("recv %s\n",pInfo);
delete[] pInfo; //这里释放了发送线程里创建的堆
break;
}
}