所有内核对象里面事件内核对象是最简单的一个,它包括一个使用计数,还有两个布尔值。一个布尔值用来表示事件是手动重置事件还是自动重置事件,另一个布尔值表示当前是否处于触发状态。
当一个手动重置事件被触发的时候,所有等待该事件的线程都能变成调度状态。而一个自动重置事件被触发的时候,等待该事件的线程里面只有一个会变成调度状态。
创建一个事件的函数原型如下:
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
非常感谢海盗,受益匪浅!