c++中CreateEvent函数解析(1)
函数原型:
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // SDBOOL bManualReset, // reset typeBOOL bInitialState, // initial stateLPCTSTR lpName // object name
);
lpEventAttributes:指向SECURITY_ATTRIBUTES结构体,此结构体决定函数的返回句柄是否可以让子进程继承。如果这个参数为NULL,这个句柄是不能继承的。一般情况下,这个参数设置为NULL。
bManualReset:指定将创建的EVENT是自动复位还是手动复位。如果为TRUE,需要用ResetEvent(HANDLE)函数手动复位状态为无信号,即一旦改EVENT被设置成有信号,则它会一直等到ResetEvent调用时才为无信号状态。如果为FALSE,当一个有信号的等待线程被释放后,系统会自动复位状态为无信号状态。
bInitialState:指定事件对象的初始状态。如果为TRUE,初始状态为有信号,否则为无信号。
lpName: 事件对象的名称,以字符串表示。名称的长度受MAX_PATH的限制,名称是大小写敏感的。如果lpName匹配一个存在的命名的事件对象,函数将请求EVENT_ALL_ACCESS来访问存在的对象。在这种情况下,bManualReset和bInitialState 被忽略,因为这两个参数已经被存在的事件设置。如果lpEventAttributes参数不为NULL,这个参数可以决定是否句柄被继承,但是它的安全描述(security-descriptor)成员被忽略。如果lpName 为NULL,创建一个没有名称的事件。如果lpName 匹配一个存在的semaphore, mutex, waitable timer, job或者file-mapping对象的名称,函数调用失败,GetLastError函数返回ERROR_INVALID_HANDLE。由于这些对象共享相同的命名空间,才导致这种情况的发生。
返回值: 函数返回句柄,该句柄具有EVENT_ALL_ACCESS权限去访问新的事件对象,同时它可以在任何需要事件对象句柄的函数中使用。
调用过程中的任何线程,都可以在一个等待函数中指定事件对象句柄。当指定的对象的状态为有信号时,单对象等待函数(例如WaitForSingleObject)返回。对于多对象等待函数(例如WaitForMultipleObjects),可以指定为任意或所有指定的对象被置为有信号状态。当等待函数返回时,等待线程将被释放去继续它的执行。 事件对象的初始状态由bInitialState参数指定,用SetEvent函数可以设置对象为有信号状态,用ResetEvent函数可以设置对象为无信号状态。 当一个手动复原的事件对象的状态被置为有信号状态时,该对象将一直保持有信号状态,直至明确调用ResetEvent函数将其置为无符号状态。当事件对象被设置为有信号状态时,任何数量的等待线程或者随后等待的线程都会被释放。
当一个自动复原事件对象的状态被设置为有信号状态时,该对象一直保持有信号状态,直至一个单等待线程被释放;系统然后会自动重置对象到无信号状态。
多个进程可持有同一个事件对象的多个句柄,可以通过使用此对象来实现进程间的同步。下面的对象共享机制是可行的:
·在CreateEvent函数中,lpEventAttributes参数指定句柄可被继承时,通过CreateProcess函数创建的子进程继承的事件对象句柄。
·一个进程可以在DuplicateHandle函数中指定事件对象句柄,从而获得一个复制的句柄,此句柄可以被其它进程使用。
·一个进程可以在OpenEvent或CreateEvent函数中指定一个名字,从而获得一个有名的事件对象句柄。(在调用OpenEvent或CreateEvent函数时,一个进程可以指定事件对象的名字。)
使用CloseHandle函数关闭句柄。当进程终止时,系统将自动关闭句柄。事件对象会被销毁,当最后一个句柄被关闭。
二、c++CreateEvent函数在多线程中使用及实例
下面主要演示一下采用CreateEvent实现多线程。
例子很简单,主要测试CreateEvent中bManualReset:和bInitialState参数的取值在线程调用中信号状态的情况。
测试1:
bManualReset:TRUE
bInitialState:TRUE
CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态
example.cpp
#include "iostream" #include "windows.h" using namespace std; DWORD WINAPI ThreadProc1(LPVOID lpParam); DWORD WINAPI ThreadProc2(LPVOID lpParam); HANDLE hEvent = NULL; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; int main(int argc, char *args[]) { hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)</span>; //使用手动重置为无信号状态,初始化时有信号状态 //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态 //if (SetEvent(hEvent)) //{ // cout << "setEvent 成功" <<endl; //} hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL); Sleep(200); hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL); Sleep(200); if ( NULL == hThread1) { cout <<"create thread fail!"; } //DWORD dCount = ResumeThread(hThread); //cout << LOWORD(dCount) << endl; return 0; } DWORD WINAPI ThreadProc1(LPVOID lpParam) { cout <<"in thread1@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<" thread1 signaled ! "<<endl; } cout <<"in thread1 --signal"<<endl; //SetEvent(hEvent); return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParam) { cout <<"in thread2@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<"thread2 signaled ! "<<endl; } cout <<"in thread2--signal"<<endl; return 0; }
执行结果:
从结果中看,执行完线程1又执行了线程2.
由于hEvent = CreateEvent(NULL, TRUE, TRUE, NULL),使用手动重置为无信号状态,初始化时有信号状态
所以hEvent一直处于有信号状态,无论是线程1释放后,hEvent仍处于有信号状态,所以线程2正常执行了。
测试2:
bManualReset:FALSE
bInitialState:TRUE
hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态
example2.cpp
#include "iostream" #include "windows.h" using namespace std; DWORD WINAPI ThreadProc1(LPVOID lpParam); DWORD WINAPI ThreadProc2(LPVOID lpParam); HANDLE hEvent = NULL; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; int main(int argc, char *args[]) { //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态 hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); </span>//当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态 //if (SetEvent(hEvent)) //{ // cout << "setEvent 成功" <<endl; //} hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL); Sleep(200); hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL); Sleep(200); if ( NULL == hThread1) { cout <<"create thread fail!"; } //DWORD dCount = ResumeThread(hThread); //cout << LOWORD(dCount) << endl; return 0; } DWORD WINAPI ThreadProc1(LPVOID lpParam) { cout <<"in thread1@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<" thread1 signaled ! "<<endl; } cout <<"in thread1 --signal"<<endl; //SetEvent(hEvent); return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParam) { cout <<"in thread2@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<"thread2 signaled ! "<<endl; } cout <<"in thread2--signal"<<endl; return 0; }
执行结果:
从执行结果中分析,执行了线程1,线程2一直在等待,直到主线程结束。
由于hEvent = CreateEvent(NULL, FALSE, TRUE, NULL),当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态
初始执行线程1的时候,hEvent是有信号的,所以线程1正常执行;又由于bManualReset=FALSE,所以执行完线程1后,hEven
WaitForSingleObject(hEvent,INFINITE);
函数一直在等待hEvent变为有信号状态,但是当主线程执行完,还没等待到,线程2程序一直没有走下去。
测试3:
bManualReset:TRUE
bInitialState:FALSE
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态
example3.cpp
#include "iostream" #include "windows.h" using namespace std; DWORD WINAPI ThreadProc1(LPVOID lpParam); DWORD WINAPI ThreadProc2(LPVOID lpParam); HANDLE hEvent = NULL; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; int main(int argc, char *args[]) { //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态 //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态 hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态</span> //if (SetEvent(hEvent)) //{ // cout << "setEvent 成功" <<endl; //} hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL); Sleep(200); hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL); Sleep(200); if ( NULL == hThread1) { cout <<"create thread fail!"; } //DWORD dCount = ResumeThread(hThread); //cout << LOWORD(dCount) << endl; return 0; } DWORD WINAPI ThreadProc1(LPVOID lpParam) { cout <<"in thread1@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<" thread1 signaled ! "<<endl; } cout <<"in thread1 --signal"<<endl; //SetEvent(hEvent); return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParam) { cout <<"in thread2@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<"thread2 signaled ! "<<endl; } cout <<"in thread2--signal"<<endl; return 0; }
执行结果,可想而知,只能输出:
in thread1@!
in thread2@!
因为初始为无信号状态,所以hEvent一直处于无信号状态,因此这两个线程一直在等待,直到主线程结束。
修改:放开例子中的注释部分:
if (SetEvent(hEvent))//设置信号为有信号状态
{
cout << "setEvent 成功" <<endl;
}
执行结果:
可见,线程1和线程2都执行了。
因为调用SetEvent,事件变为有信号状态,线程1执行;又由于线程1释放后,hEvent仍旧处于有信号状态,所以线程2也执行了。
再修改:在线程1中,添加ResetEvent(hEvent)(手动设置事件为无信号状态),则线程2不会执行。
测试4:
bManualReset:FALSE
bInitialState:FALSE
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//线程释放后自动重置为无信号状态,初始化时为无信号状态
example4.cpp
#include "iostream" #include "windows.h" using namespace std; DWORD WINAPI ThreadProc1(LPVOID lpParam); DWORD WINAPI ThreadProc2(LPVOID lpParam); HANDLE hEvent = NULL; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; int main(int argc, char *args[]) { //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态 //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态 //hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态 if (SetEvent(hEvent)) { cout << "setEvent 成功" <<endl; } hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL); Sleep(200); hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL); Sleep(200); if ( NULL == hThread1) { cout <<"create thread fail!"; } //DWORD dCount = ResumeThread(hThread); //cout << LOWORD(dCount) << endl; return 0; } DWORD WINAPI ThreadProc1(LPVOID lpParam) { cout <<"in thread1@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<" thread1 signaled ! "<<endl; } cout <<"in thread1 --signal"<<endl; //SetEvent(hEvent); return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParam) { cout <<"in thread2@!"<<endl; DWORD dReturn = WaitForSingleObject(hEvent,INFINITE); if ( WAIT_OBJECT_0 == dReturn) { cout <<"thread2 signaled ! "<<endl; } cout <<"in thread2--signal"<<endl; return 0; }
由于调用SetEvent,hEvent为有信号状态,线程1正常执行,又由于调用完线程1后,hEvent自动重置为无信号状态,所以线程2只能在等待,直到主线程退出。
修改:线程1中的SetEvent(hEvent);的注释去掉,再运行,则线程1和线程2 都会执行。
c++中CreateEvent函数解析(1)相关推荐
- c++中CreateEvent函数解析(2)
函数原型: HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // SD BOOL bManualReset, // reset ...
- oracle中next_day()函数解析
oracle中next_day()函数解析 Sql代码 当前系统时间的下一星期一的时间select next_day(sysdate,1) from dual NEXT_DAY(date,char ...
- python中append函数解析_对python中的pop函数和append函数详解
对python中的pop函数和append函数详解 pop()函数 1.描述 pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值. 语法 pop()方法语法: list. ...
- 【ROS学习】- tf学习 - tf中重要函数解析 (陆续更新....)
文章目录 一.函数waitForTransform().lookupTransform() 具体解释 二.函数 tf::StampedTransform().sendTransform() 具体解释 ...
- c++中CreateEvent函数
http://blog.csdn.net/chenyujing1234/article/details/8572921 函数原型: [cpp] view plain copy HANDLE Crea ...
- 【晕头晕脑的Python】Python中Reshape函数解析
Reshape函数解析 Reshape()作用: Reshape()实例说明: 一维reshape() 为 二维 二维数组 reshape 切片,逆置 三维Reshape情况 Reshape()作用: ...
- java中main函数解析
作者:xwdreamer 出处:http://www.cnblogs.com/xwdreamer 欢迎任何形式的转载,但请务必注明出处. 从写java至今,写的最多的可能就是主函数 public st ...
- java中的de是什么_【转】java中main函数解析
源地址:http://www.cnblogs.com/xwdreamer/archive/2012/04/09/2438845.html 从写java至今,写的最多的可能就是主函数 public st ...
- java中的主函数_java中main函数解析
从写java至今,写的最多的可能就是主函数 public static void main(String[] args) {} 但是以前一直都没有问自己,为什么要这么写,因为在c语言中就没有这样子的要 ...
最新文章
- 独家 | 虚假疫苗网站如何获取你的个人信息
- 【数学建模】MATLAB应用实战系列(九十一)-熵权法应用案例(附MATLAB和Python代码)
- 复杂多边形光栅化算法
- redis和mecache和ehcache的特点
- Spring EL中的类操作符
- Ext 2.0布局实例
- php 架构师之路ioc讲解
- 360怎么修改域名服务器地址,怎样修改DNS地址
- 创业之前必须要做的八个测试
- 在本地计算机无法启动t6,启动用友T6时出现“不能登录到服务器[]请检查T6管理服务是否已启动。...
- class uesrfun.php,帝国cms教程:列表页面批量添加Tags -电脑资料
- 英语学习--chap7 形容词
- unrecognized selector sent to instance 0x7fbb51c7c490问题解决方法之一
- 原创电子书《菜鸟程序员成长之路:从技术小白到阿里巴巴Java工程师》
- 自用房屋租住管理系统
- 冲孔网——现在普遍应用的装饰产品-KAIYAO
- 如何用JavaScript自己实现一个unshift() 方法
- Unity3D 游戏引擎之构建简单的游戏世界(三)
- 网络变压器作用(续):带中间抽头的两个线圈组成的网络变压器及其作用
- Android中的IPC方式
热门文章
- linux卸载anaconda_Win10安装Anaconda和Pytorch(CPU版)
- html5步骤条,自定义步骤条 , 纯原生html + css
- UE4学习-鼠标事件(按下、释放、物体抓取、计算重量、触发开门)
- 直接销毁_战机报废,发动机怎么处理?美国直接销毁,中国改造成扫雪神器
- php获取控制器返回,从php中的mvc控制器方法返回一个json值
- cocos2dx ios入口类_2.cocos2d-x 第一个项目
- python tkinter计算器实例_Python编程使用tkinter模块实现计算器软件完整代码示例
- 干货 | extern的用法解析
- 很火的WiFi6,了解一下
- 《c语言从入门到精通》看书笔记——第11章 结构体和共用体