MFC 主线程等待子线程退出函数(MsgWaitForMultipleObjects)

本文详细解析了如何使用MsgWaitForMultipleObjects函数实现在多线程环境中,即使在阻塞状态下也能响应消息的技巧。通过合理管理线程句柄数组,确保线程退出时能及时调整,避免消息遗漏,实现线程与消息队列的高效同步。

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


void WaitForThreadExit(void)
{
	DWORD dwRet;
	MSG msg;
	int wait_count=4;//线程句柄有4个
	int nExitThreadCount=0;

	while(1)
	{
		dwRet = MsgWaitForMultipleObjects(wait_count, hArray, FALSE, INFINITE, QS_ALLINPUT);

		if (dwRet == WAIT_OBJECT_0 + wait_count)
		{
            //消息到达队列,需要对消息进行重判断防止意外退出或卡死
			while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))//获取队列消息 PM_REMOVE -PeekMessage处理后,消息从队列里除掉。
			{
				if (msg.message==WM_QUIT||msg.message==WM_CLOSE)  
				{

					break;
				}

				TranslateMessage(&msg);//将虚拟键消息转换为字符消息
				DispatchMessage(&msg);//发一个消息给窗口程序
			}
		}

		else if (dwRet >= WAIT_OBJECT_0 && dwRet < WAIT_OBJECT_0+ wait_count)
		{
            //线程组中返回消息
			nExitThreadCount++;
			if (nExitThreadCount < 4)
			{

				TRACE("一个线程退出了\n");

				int nIndex=dwRet-WAIT_OBJECT_0;

				hArray[nIndex]=hArray[wait_count-1];

				hArray[wait_count-1]=NULL;
				wait_count--;
			}
			else
			{
				TRACE("4个线程都退出了\n");

				break;
			}
		}
		else
		{
            //错误退出
			DWORD dErrCode=GetLastError();

			break;
		}

	}
}

MsgWaitForMultipleObjects

函数功能:阻塞时仍可以响应消息

MsgWaitForMultipleObjects()函数类似WaitForMultipleObjects(),

但它会在“对象被激发”或“消息到达队列”时被唤醒而返回。

MsgWaitForMultipleObjects()多接收一个参数,允许指定哪些消息是观察对象。

DWORD MsgWaitForMultipleObjects(
  DWORD nCount,          // 表示pHandles所指的handles数组的元素个数,最大容量是MAXIMUM_WAIT_OBJECTS 
  LPHANDLE pHandles,     // 指向一个由对象handles组成的数组,这些handles的类型不需要相同
  BOOL fWaitAll,         // 是否等待所有的handles被激发才返回
  DWORD dwMilliseconds,  // 超时时间
  DWORD dwWakeMask       // 欲观察的用户输入消息类型
);

返回值

WAIT_TIMEOUT :因时间终了而返回

WAIT_OBJECT_0 :当bWaitAll是TRUE

WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount – 1) :

bWaitAll是FALSE,将返回值减去WAIT_OBJECT_0,就表示数组中哪一个handle被激发了

WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount – 1) :等待的对象中有任何mutexes

WAIT_FAILED :函数失败时返回该值,可以使用GetLastError()找出失败的原因

WAIT_OBJECT_0 + nCount :消息到达队列 

MsgWaitForMultipleObjects()的正确使用方式是改写主消息循环,

使得激发状态的handles得以像消息一样被对待。

通常程序中只会有一个地方调用MsgWaitForMultipleObjects(),而这个调用存在于消息循环中。

注意:

1. 在收到WM_QUIT之后,Windows仍然会传送消息给你,

如果要在收到WM_QUIT之后等待所有线程结束,必须继续处理你的消息,

否则窗口会变得反应迟钝,而且没有重绘能力。

2.MsgWaitForMultipleObjects()不允许handles数组中有缝隙产生。

所以当某个handle被激发了时,应该在下一次调用MsgWaitForMultipleObjects之前

先把handles数组做个整理、紧压,不要只是把数组中的handle设为NULL

3.如果有另一个线程改变了对象数组,而那是你正在等待的,

那么需要一种方法,可以强迫MsgWaitForMultipleObjects返回,

并重新开始,以包含新的handle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值