函数功能:该函数将一个消息放入 (寄送)到指定线程的消息队列里,不等待线程处理消息就返回。
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; } |