函數功能:該函數将一個消息放入 (寄送)到指定線程的消息隊列裡,不等待線程處理消息就傳回。
函數原型:BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM IParam);
參數
idThread:其消息将被寄送的線程的 線程辨別符。如果線程沒有消息隊列,此函數将失敗。當線程第一次調用一個Win 32 USER或GDI函數時,系統建立線程的消息隊列。要得到更多的資訊,參見備注。
Msg:指定将被寄送的消息的類型。
wParam:指定附加的消息特定資訊。
IParam:指定附加的消息特定資訊。
傳回值:如果函數調用成功,傳回非零值。如 果函數調用失敗,傳回值是零。若想獲得更多的錯誤資訊,請調用GetLastError函數。如果idThread不是一個有效的線程辨別符或由 idThread确定的線程沒有消息隊
列,GetLastError傳回 ERROR_INVALID_THREAD。
備注:消息将寄送到的線程必須建立消息隊 列,否則調用PostThreadMessage會失敗。用下列方法之一來處理這種情況:
調用PostThreadMessage。 如果失敗,調用Sleep,再調用PostThreadMessage,反複執行,直到PostThreadMessage成功。
建立一個事件對象,再建立線程。在調用 PostThreadMessage之前,用函數WaitForSingleObject來等特事件被設定為被告知狀态。消息将寄送到的線程調用 PeekMessage(£msg,NULL,WM_USER,WM_USER,PM_NOREMOVE)來強制系統建立消息隊列。設定事件,表示線程已 準備好接收寄送的消息。
消息将寄送到的線程通過調用 GetMesssge或PeekMesssge來取得消息。傳回的MSG結構中的hwnd成員為NULL。
速查:Windows NT:3.1及以上版本;Windows:95及以上版本;Windows CE:1.0及以上版本:頭檔案:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環境下以Unicode和ANSI方式實作。
---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
把window線程間傳送消息仔細的看了一遍,覺得以前的了解 很不深刻。說一說對PostThreadMessage的 了解。
PostThreadMessage是一個線程體發送一個消息 到指定的線程ID,其 原型如下:
BOOL PostThreadMessage(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
這個函數既可以發送消息給工 作線程,也可以發送給UI線 程。接受PostThreadMessage的 線程必須已經有了一個message queue, 否則調用PostThreadMessage會 失敗。因為此原因使用GetLastError會 得到錯誤碼為1444, 這種情況經常出現,解決方法有如下兩種:
1. 調 用PostThreadMessage, 如果失敗,就Sleep一 段時間再次調用PostThreadMessage直 到調用成功;
2. 創 建一個Event對 象,讓PostThreadMessage等 待接受的線程建立一個message queue。 可以通過調用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;
}
}
}
}
PostThreadMessage傳遞的消息如果要包含信 息,要注意在結束的時候釋放消息中的資訊。在消息中附加資訊方法如下
/*構造資訊如下*/
char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg
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;
}
}
做了一個簡單的消息通信實驗,讓主 線程中等待使用者輸入,産生不同的消息,并把這些消息post給 子線程,子線程根據産生的消息做出不同的反映。這些子線程可以是工作線程也可以是UI線程。
#include <windows.h> #include <cstdio> #include <process.h> #define MY_MSG WM_USER+100 const int MAX_INFO_SIZE = 20; HANDLE hStartEvent; // thread start event // thread function unsigned __stdcall fun(void *param) { printf("thread fun start \n"); MSG msg; PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); if(!SetEvent(hStartEvent)) //set thread start event { printf("set start event failed,errno:%d\n",::GetLastError()); return 1; } while(true) { 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; } } }; return 0; } int main() { HANDLE hThread; unsigned nThreadID; hStartEvent = ::CreateEvent(0,FALSE,FALSE,0); //create thread start event if(hStartEvent == 0) { printf("create start event failed,errno:%d\n",::GetLastError()); return 1; } //start thread hThread = (HANDLE)_beginthreadex( NULL, 0, &fun, NULL, 0, &nThreadID ); if(hThread == 0) { printf("start thread failed,errno:%d\n",::GetLastError()); CloseHandle(hStartEvent); return 1; } //wait thread start event to avoid PostThreadMessage return errno:1444 ::WaitForSingleObject(hStartEvent,INFINITE); CloseHandle(hStartEvent); int count = 0; while(true) { char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg sprintf(pInfo,"msg_%d",++count); if(!PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0))//post thread msg { printf("post message failed,errno:%d\n",::GetLastError()); delete[] pInfo; } ::Sleep(1000); } CloseHandle(hThread); return 0; } |
要把SETTING 改為多線程的
Project->Settings->click C/C tab,
在Category 中選Code Generation, 然後在Use run-time libray 中選一個
Multithread 配置