PostThreadMessage是一個線程體發送一個消息到指定的線程ID,其原型如下:
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;
}
}