WaitForMultipleObjects

// MultiThreadTest.cpp : 定义控制台应用程序的入口点。
// 测试内容:测试WaitForMultipleObjects缺陷及改进措施

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;

typedef struct  
{
	HANDLE hAdd;
	HANDLE hSub;
	HANDLE hStop;
}ST_HANDLES;

DWORD CALLBACK ThreadMulti(void* pParam)
{
	if(!pParam)
		return 1;

	ST_HANDLES* pHandle = (ST_HANDLES*) pParam;
	HANDLE szHandle[] = {pHandle->hAdd, pHandle->hSub, pHandle->hStop};
	while(1)
	{
		// 参数三为TRUE时, 三个状态同时触发是才返回, Add, Sub ,Stop 一起触发时返回, 但是只进入case WAIT_OBJECT_0 + 0,适用于多个事件触发一条响应
		// 参数三为FALSE时, 优先处理最小索引的hAdd,当hAdd频繁触发时,hSub和hStop将得不到处理的机会;
		int nRet = WaitForMultipleObjects(3, szHandle, FALSE, INFINITE);
		switch(nRet)
		{
		case WAIT_FAILED:
			{
				return 1;
			}
			break;
		case WAIT_TIMEOUT:
			{

			}
			break;
		case WAIT_OBJECT_0 + 0:
			{
				// hAdd
				cout << "+" << endl;
			}
			break;
		case WAIT_OBJECT_0 + 1:
			{
				// hSub
				cout << "-" << endl;
			}
			break;
		case WAIT_OBJECT_0 + 2:
			{
				// hStop
				cout << "stop" << endl;
				return 0;
			}
			break;
		}
	}
	
}

int ProcessHandle(int nIndex)
{
	switch(nIndex)
	{
	case 0:
		{
			cout << "+" ;
		}
		break;
	case 1:
		{
			cout << "-" << endl;
		}
		break;
	case 2:
		{
			cout << "stop" << endl;
			return 0;
		}
		break;
	}
	return 1;
}

DWORD CALLBACK ThreadMultiEx(void* pParam)
{
	if(!pParam)
		return 0;

	ST_HANDLES* pHandle = (ST_HANDLES*) pParam;
	HANDLE szHandle[] = {pHandle->hAdd, pHandle->hSub, pHandle->hStop};
	int nCount = sizeof(szHandle) / sizeof(HANDLE);
	int nIndex = 0 ;
	//while(WAIT_OBJECT_0 != WaitForSingleObject(pHandle->hStop, 300))
	while(1)
	{
		int nRet = WaitForMultipleObjects(3, szHandle, FALSE, 300);
		switch(nRet)
		{
		case WAIT_FAILED:
			{
				//错误...
				return 1;
			}
			break;
		case WAIT_TIMEOUT:
			{
				//超时...
			}
			break;
		default:
			{
				nIndex = nRet - WAIT_OBJECT_0;
				int nCheck = ProcessHandle(nIndex++);// 处理当前事件
				if(0 == nCheck)
					return 0;

				while(nCount > nIndex)
				{
					nRet = WaitForMultipleObjects(nCount - nIndex, &szHandle[nIndex], FALSE, 0);
					switch(nRet)
					{
					case WAIT_FAILED:
						{
							//错误...
							return 1;
						}
						break;
					case WAIT_TIMEOUT:
						{
							//超时...
							nIndex = nCount; //退出检测,因为没有被触发的对象了.
						}
						break;
					default:
						{
							nIndex = nIndex + nRet - WAIT_OBJECT_0;
							nCheck = ProcessHandle(nIndex++);
							if(0 == nCheck)
								return 0;
						}
						break;
					}
				}
			}
			break;
		}
	}
	return 0;
}

DWORD CALLBACK AddEvent(void* pParam)
{
	ST_HANDLES* pHandle = (ST_HANDLES*) pParam;
// 	while(1)
// 	{	
// 		SetEvent(pHandle->hAdd);// 无限循环SetEvent 让CPU分配给线程资源Multi时没有时间处理hStop和 - 事件
// 	}

	while(WAIT_OBJECT_0 != WaitForSingleObject(pHandle->hStop, 300))
	{	
		SetEvent(pHandle->hAdd);//正常写代码
	}
	return 0;
}

DWORD CALLBACK SubEvent(void* pParam)
{
 	ST_HANDLES* pHandle = (ST_HANDLES*) pParam;
// 	while(1)
// 	{	
// 		SetEvent(pHandle->hSub); 
// 	}

	while(WAIT_OBJECT_0 != WaitForSingleObject(pHandle->hStop, 300))
	{	
		SetEvent(pHandle->hSub);//正常写代码
	}
	return 0;
}

void StopEvent(ST_HANDLES& stHandles,HANDLE& hMultiThread, HANDLE& hAddThread, HANDLE& hSubThread )
{
	SetEvent(stHandles.hStop);
//  为了测试效果将以下正常状态代码注释
// 	if(WaitForSingleObject(hMultiThread, 1000) == WAIT_TIMEOUT)
// 		TerminateThread(hMultiThread, 0);
// 	hMultiThread = NULL;
// 
// 	if(WaitForSingleObject(hAddThread, 1000) == WAIT_TIMEOUT)
// 		TerminateThread(hAddThread, 0);
// 	hAddThread = NULL;
// 
// 	if(WaitForSingleObject(hSubThread, 1000) == WAIT_TIMEOUT)
// 		TerminateThread(hSubThread, 0);
// 	hSubThread = NULL;
// 
// 	if(stHandles.hAdd)
// 	{
// 		CloseHandle(stHandles.hAdd);
// 		stHandles.hAdd = NULL;
// 	}
// 
// 	if(stHandles.hSub)
// 	{
// 		CloseHandle(stHandles.hSub);
// 		stHandles.hSub = NULL;
// 	}
// 
// 	if(stHandles.hStop)
// 	{
// 		CloseHandle(stHandles.hStop);
// 		stHandles.hStop = NULL;
// 	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hAdd = CreateEvent(NULL, FALSE, FALSE, NULL);
	HANDLE hSub = CreateEvent(NULL, FALSE, FALSE, NULL);
	HANDLE hStop = CreateEvent(NULL, TRUE, FALSE, NULL);
	ST_HANDLES stHandles;
	stHandles.hAdd = hAdd;
	stHandles.hSub = hSub;
	stHandles.hStop = hStop;
	// 该方式会导致高索引位的hSub,hStop无法执行
	//HANDLE hMultiThread = CreateThread(NULL, NULL, ThreadMulti, (void*)&stHandles, NULL, NULL);

	// 使用双WaitForMultipleObject 确保高索引位的事件也可以执行
	HANDLE hMultiThread = CreateThread(NULL, NULL, ThreadMultiEx, (void*)&stHandles, NULL, NULL);
	HANDLE hAddThread = CreateThread(NULL, NULL, AddEvent, (void*)&stHandles, NULL, NULL);
	HANDLE hSubThread = CreateThread(NULL, NULL, SubEvent, (void*)&stHandles, NULL, NULL);
	getchar();
	StopEvent(stHandles, hMultiThread, hAddThread, hSubThread);
	getchar();
	return 0;
}

附:以上方法是使用用户模式的线程机制,效率高,如果需要考虑线程同步问题,应该首先考虑用户模式的线程同步方法,但是,用户模式的线程同步有限制,对于多个进程之间的线程同步,用户模式的线程同步方法无能为力,这时,只能考虑使用内核模式。
内核模式:MsgWaitForMultipleObjects;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值