理解PostThreadMessage(转载)

本文详细探讨了Windows中PostThreadMessage函数的使用方法及其注意事项。包括如何确保目标线程已准备好接收消息,如何在消息中附加及释放信息,以及通过示例代码展示了主线程与子线程间的简单消息通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

window线程间传送消息仔细的看了一遍,觉得以前的理解很不深刻。说一说对PostThreadMessage的理解。

PostThreadMessage是一个线程体发送一个消息到指定的线程ID,其原型如下:

BOOLPostThreadMessage(
 DWORDidThread,
 UINTMsg,
 WPARAMwParam,
 LPARAMlParam
);

这个函数既可以发送消息给工作线程,也可以发送给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){
	 int nRet = 0;
 if(nRet = GetMessage(&msg, 0,0,0)) {
		if (nRet == -1)
			break;
 switch(msg.message){
   case WM_MESSAGE_A:
 ……
 break;
  }
 }
 }
}

PostThreadMessage传递的消息如果要包含信息,要注意在结束的时候释放消息中的信息。在消息中附加信息方法如下

/*构造信息如下*/
char*pInfo=newchar[MAX_INFO_SIZE];//createdynamicmsg
sprintf(pInfo,"msg_%d",++count);
PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0)//postthreadmsg
/*解释信息如下*/
if(GetMessage(&msg,0,0,0))//getmsgfrommessagequeue
{
switch(msg.message)
{
caseMY_MSG:
char*pInfo=(char*)msg.wParam;
printf("recv%s/n",pInfo);
delete[]pInfo; //这里释放了资源
break;
}
}

做了一个简单的消息通信实验,让主线程中等待用户输入,产生不同的消息,并把这些消息post给子线程,子线程根据产生的消息做出不同的反映。这些子线程可以是工作线程也可以是UI线程。


#include<windows.h>
#include<cstdio>
#include<process.h>

#defineMY_MSGWM_USER+100
constintMAX_INFO_SIZE=20;

HANDLEhStartEvent;//threadstartevent

//threadfunction
unsigned__stdcallfun(void*param)
{
printf("threadfunstart/n");

MSGmsg;
PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_NOREMOVE);

if(!SetEvent(hStartEvent))//setthreadstartevent
{
printf("setstarteventfailed,errno:%d/n",::GetLastError());
return1;
}

while(true)
{
if(GetMessage(&msg,0,0,0))//getmsgfrommessagequeue
{
switch(msg.message)
{
caseMY_MSG:
char*pInfo=(char*)msg.wParam;
printf("recv%s/n",pInfo);
delete[]pInfo;
break;
}
}
};
return0;
}

intmain()
{
HANDLEhThread;
unsignednThreadID;

hStartEvent=::CreateEvent(0,FALSE,FALSE,0);//createthreadstartevent
if(hStartEvent==0)
{
printf("createstarteventfailed,errno:%d/n",::GetLastError());
return1;
}

//startthread
hThread=(HANDLE)_beginthreadex(NULL,0,&fun,NULL,0,&nThreadID);
if(hThread==0)
{
printf("startthreadfailed,errno:%d/n",::GetLastError());
CloseHandle(hStartEvent);
return1;
}

//waitthreadstarteventtoavoidPostThreadMessagereturnerrno:1444
::WaitForSingleObject(hStartEvent,INFINITE);
CloseHandle(hStartEvent);

intcount=0;
while(true)
{
char*pInfo=newchar[MAX_INFO_SIZE];//createdynamicmsg
sprintf(pInfo,"msg_%d",++count);
if(!PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0))//postthreadmsg
{
printf("postmessagefailed,errno:%d/n",::GetLastError());
delete[]pInfo;
}
::Sleep(1000);
}

CloseHandle(hThread);
return0;
}


要把SETTING 改为多线程的
Project->Settings->click C/C tab,
在Category 中选Code Generation, 然后在Use run-time libray 中选一个
Multithread 配置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值