函數功能:該函數將一個消息放入 (寄送)到指定線程的消息隊列裏,不等待線程處理消息就返回。
windows
函數原型:BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM IParam);多線程
參數函數
idThread:其消息將被寄送的線程的 線程標識符。若是線程沒有消息隊列,此函數將失敗。當線程第一次調用一個Win 32 USER或GDI函數時,系統建立線程的消息隊列。要獲得更多的信息,參見備註。post
Msg:指定將被寄送的消息的類型。spa
wParam:指定附加的消息特定信息。線程
IParam:指定附加的消息特定信息。code
返回值:若是函數調用成功,返回非零值。如 果函數調用失敗,返回值是零。若想得到更多的錯誤信息,請調用GetLastError函數。若是idThread不是一個有效的線程標識符或由 idThread肯定的線程沒有消息隊orm
列,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 ![]() 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; } |