PostThreadMessage 向线程发送消息
说明:
函数功能:该函数将一个消息放入(寄送)到指定线程的消息队列里,不等待线程处理消息就返回。
函数原型:
BOOL PostThreadMessage(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM IParam);
参数
idThread:其消息将被寄送的线程的线程标识符。如果线程没有消息队列,此函数将失败。当线程第一次调用一个Win32 USER或GDI函数时,系统创建线程的消息队列.
Msg:指定将被寄送的消息的类型。
wParam:指定附加的消息特定信息。
IParam:指定附加的消息特定信息。
这个函数既可以发送消息给工作线程,也可以发送给UI线程。
接受PostThreadMessage的线程必须已经有了一个message queue,否则调用PostThreadMessage会失败。
因为此原因使用GetLastError会得到错误码为1444,这种情况经常出现,解决方法有如下两种:
1. 调用PostThreadMessage,如果失败,就Sleep一段时间再次调用PostThreadMessage直到调用成功;
2. 创建一个Event对象,让PostThreadMessage等待接受的线程创建一个message queue。可以通过调用PeekMessage强制系统创建一个message queue。
示例代码如下:
假设mainAPP是发送线程ThreadA是接受线程,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 */
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;
}
}
参数生命周期
在内存理解上,最著名的例子就是线程启动时的参数传递。
函数启动一个线程,很多时候需要向线程传参数,但是线程是异步启动的,即很可能启动函数已经退出了,而线程函数都还没有正式开始运行,
因此,绝不能用启动函数的内部变量给线程传参。道理很简单,函数的内部变量在浮动栈,但函数退出时,浮动栈自动拆除,内存空间已经被释放了。
当线程启动时,按照给的参数指针去查询变量,实际上是在读一块无效的内存区域,程序会因此而崩溃。
那怎么办呢?我们应该直接用malloc函数给需要传递的参数分配一块内存区域,将指针传入线程,线程收到后使用,最后线程退出时,free释放。