// 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;