c++中CreateEvent函数
参考:https://blog.csdn.net/u011642774/article/details/52789969
函数原型:
- HANDLE CreateEvent(
- LPSECURITY_ATTRIBUTES lpEventAttributes, // SD
- BOOL bManualReset, // reset type
- BOOL bInitialState, // initial state
- LPCTSTR 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函数的更多相关文章
- 线程中CreateEvent和SetEvent及WaitForSingleObject的用法
首先介绍CreateEvent是创建windows事件的意思,作用主要用在判断线程退出,线程锁定方面. CreateEvent 函功能描述:创建或打开一个命名的或无名的事件对象. EVENT有两种状态 ...
- Oracle 中 decode 函数用法
Oracle 中 decode 函数用法 含义解释:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译 ...
- mysql中now()函数的使用,还有oracle的sysdate,可能埋下的坑
mysql中now()函数的使用,还有oracle的sysdate 在需求中如果系统中药添加当前操作的时间那么很简单的一个操作在写sql的时候直接在这个字段对应的位置写上now()函数就可以了,这样就 ...
- 程序代码中退出函数exit()与返回函数return ()的区别
程序代码中退出函数exit()与返回函数return ()的区别 exit(0):正常运行程序并退出程序: exit(1):非正常运行导致退出程序: return():返回函数,若在主函数 ...
- mysql中find_in_set()函数的使用
首先举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有 1头条.2推荐.3热点.4图文等等 .现在有篇文章他既是头条,又是热点,还是图文,type中以 1,3,4 的格式存储.那我 ...
- QT中使用函数指针
想仿命令行,所以定义了一个类,让一个String 对应一个 function,将两者输入list容器. 类中定义了 QString commandStr; void (MainWindow::*com ...
- Bash 是如何从环境变量中导入函数的
在上文中曾说到: 所谓的环境变量的真实面目其实就是个任意字符串 Bash 在启动时会将 environ 数组中包含 = 号的字符串导入成为自己的变量 Bash 在启动外部命令时会将自己内部标记为环境变 ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
- PHP中spl_autoload_register()函数的用法
spl_autoload_register (PHP 5 >= 5.1.2) spl_autoload_register — 注册__autoload()函数 说明 bool spl_autol ...
随机推荐
- linux下使用split命令分割文件且文件号从1开始
Linux里切割大文件的命令如下: split [OPTION] [INPUT [PREFIX]] 选项如下: -a : 指定后缀长度 -b : 每个文件多少字节 -d : 使用数字后缀而不是字母 - ...
- linux 下分别使用pip2、pip3
上次切换了Python2和Python3.但是Python3并没有pip,所有在Python3下不能安装包. 下面实现在Python3 下安装pip3 1,首先安装setuptools wget -- ...
- 【小白学PyTorch】4 构建模型三要素与权重初始化
文章目录: 目录 1 模型三要素 2 参数初始化 3 完整运行代码 4 尺寸计算与参数计算 1 模型三要素 三要素其实很简单 必须要继承nn.Module这个类,要让PyTorch知道这个类是一个Mo ...
- AndroidStudio中利用git下载github或者git.oschina的代码时报错:repository test has failed解决方法
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 微博:http://weibo.com/mcxiaobing AndroidS ...
- 删除MBR分区如何使用光盘恢复
1.备份MBR分区表 dd if=/dev/sda of=/data/mbr.bak bs=1 count=64 skip=446 分区表前512字节分为三部分,第一部分446字节与启动相关 ...
- Hexo-butterfly-magicv3.0.1(持续更新中....)
介绍 Hexo-butterfly魔改v3.0.1 软件架构 本项目是基于Hexo静态博客的个性主题---蝴蝶主题魔改版 安装教程 克隆 安装依赖 hexo命令生成public文件夹 启动hexo-s ...
- iptables实用知识 ,一文学会配置linux防火墙
目录 1.防火墙的概念 2. linux防火墙 3.linux数据包处理流程 3.1 linux 防火墙将以上流程,固定区分为5个流程节点 3.2 数据流程 4 linux防火墙的实现机制 4.1 i ...
- 莫名其妙的Explain Plan
两张表的建表语句: CREATE TABLE hy_emp ( empno NUMBER(8,0) not null primary key, ename NVARCHAR2(60) not null ...
- Java Web制作登录 验证码
具体操作如下: 新建一个servlet,代码如下:标记一个WebServlet, @WebServlet(urlPatterns = {"/checkCode"}) //验证码Se ...
- sqlserver语句的执行顺序
执行顺序: 1.from 2.where 3.group by 4.having 5.根据select 关键之后的要显示的字段,进行结果集显示 6.order by 对最终结果集进行排序 7.top/ ...