多线程系列之——事件内核对象

所有内核对象里面事件内核对象是最简单的一个,它包括一个使用计数,还有两个布尔值。一个布尔值用来表示事件是手动重置事件还是自动重置事件,另一个布尔值表示当前是否处于触发状态。

当一个手动重置事件被触发的时候,所有等待该事件的线程都能变成调度状态。而一个自动重置事件被触发的时候,等待该事件的线程里面只有一个会变成调度状态。

创建一个事件的函数原型如下:

HANDLE WINAPI CreateEvent(
  __in_opt  LPSECURITY_ATTRIBUTES lpEventAttributes,
  __in      BOOL bManualReset,
  __in      BOOL bInitialState,
  __in_opt  LPCTSTR lpName
);

第一个参数是安全描述符,设为NULL表示使用默认的安全描述符,并且子进程无法继承返回的句柄。

第二个参数TRUE表示手动重置,FALSE表示自动重置。

第三个参数FALSE表示事件是未触发状态,TRUE表示事件是触发状态。

第四个参数为事件指定一个名字。如果已经存在,如果已经存在,函数则请求事件的EVENT_ALL_ACCESS权限,此时其它参数将被忽略。(程序只运行一个实例就可以使用这个方法,检测到事件已经存在则退出)

SetEvent设置事件为触发状态,ResetEvent设置事件为未触发状态。

句柄一定要关闭,通过CloseHandle。

WaitForSingleOeject和WaitForMultipleObjects对自动重置事件有个副作用,等待成功后会将事件重置为未触发状态。

 

通过两个例子程序来感受下事件的便利。

现在有三个顾客进了烟酒店,分别要了三包不通的香烟,老板去取香烟,这三个顾客就在柜台前等待(等待事件),老板取来了香烟(事件变成触发状态),付账、拿烟、离开。

第一个例子程序使用手动重置事件,事件出发后,三个顾客可以同时离开。

#include <windows.h>
#include <iostream>

using namespace std;

HANDLE hEvent;//全局事件

DWORD WINAPI CustomerOne(LPVOID lp)
{
	cout << "顾客1:老板,拿包8mg的红双喜" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顾客1:这种红双喜非常清爽,谢谢。" << endl;

	return 0;
}

DWORD WINAPI CustomerTwo(LPVOID lp)
{
	cout << "顾客2:14块的利群" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顾客2:我喜欢这个香烟,谢谢老板。" << endl;

	return 0;
}

DWORD WINAPI CustomerThree(LPVOID lp)
{
	cout << "顾客3:我要包8mg的中南海" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顾客3:一般人抽不惯这个,不过我一直都抽这个。" << endl;

	return 0;
}

int main(int argc, char *argv[])
{
	hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	HANDLE hThread[3];
	hThread[0] = CreateThread(NULL,0,CustomerOne,0,0,NULL);
	hThread[1] = CreateThread(NULL,0,CustomerTwo,0,0,NULL);
	hThread[2] = CreateThread(NULL,0,CustomerThree,0,0,NULL);

	Sleep(1000);
	cout << "老板:你们要的香烟。" << endl;
	SetEvent(hEvent);

	WaitForMultipleObjects(3,hThread,TRUE,INFINITE);
	cout << endl << "所有线程都退出" << endl;

	CloseHandle(hEvent);
	for(int i = 0;i < 3;++i)
		CloseHandle(hThread[i]);

	return 0;
}


第二个例子使用自动重置事件,三个顾客分别先后离开。(等待成功的副作用,所以三个线程不能同时执行。每个线程等待成功后必须重置事件为触发状态,这样另外的线程就有机会得到执行。)

#include <windows.h>
#include <iostream>

using namespace std;

HANDLE hEvent;//全局事件

DWORD WINAPI CustomerOne(LPVOID lp)
{
	cout << "顾客1:老板,拿包8mg的红双喜" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顾客1:这种红双喜非常清爽,谢谢。" << endl;
	SetEvent(hEvent);
	cout << "顾客1离开。" << endl;

	return 0;
}

DWORD WINAPI CustomerTwo(LPVOID lp)
{
	cout << "顾客2:14块的利群" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顾客2:我喜欢这个香烟,谢谢老板。" << endl;
	SetEvent(hEvent);
	cout << "顾客2离开。" << endl;

	return 0;
}

DWORD WINAPI CustomerThree(LPVOID lp)
{
	cout << "顾客3:我要包8mg的中南海" << endl;
	WaitForSingleObject(hEvent,INFINITE);
	cout << "顾客3:一般人抽不惯这个,不过我一直都抽这个。" << endl;
	SetEvent(hEvent);
	cout << "顾客3离开。" << endl;

	return 0;
}

int main(int argc, char *argv[])
{
	hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
	HANDLE hThread[3];
	hThread[0] = CreateThread(NULL,0,CustomerOne,0,0,NULL);
	hThread[1] = CreateThread(NULL,0,CustomerTwo,0,0,NULL);
	hThread[2] = CreateThread(NULL,0,CustomerThree,0,0,NULL);

	Sleep(1000);
	cout << "老板:你们要的香烟。" << endl;
	SetEvent(hEvent);

	WaitForMultipleObjects(3,hThread,TRUE,INFINITE);
	cout << endl << "所有线程都退出" << endl;

	CloseHandle(hEvent);
	for(int i = 0;i < 3;++i)
		CloseHandle(hThread[i]);

	return 0;
}



转载自:http://blog.youkuaiyun.com/tornodo/article/details/7583136

非常感谢海盗,受益匪浅!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值