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

来源:互联网 发布:大数据行业股票 编辑:程序博客网 时间:2024/06/06 04:38

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

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

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

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.csdn.net/tornodo/article/details/7583136

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


0 0
原创粉丝点击