参考:https://blog.csdn.net/u011642774/article/details/52789969

函数原型:

  1. HANDLE CreateEvent(
  2. LPSECURITY_ATTRIBUTES lpEventAttributes, // SD
  3. BOOL bManualReset,                       // reset type
  4. BOOL bInitialState,                      // initial state
  5. LPCTSTR lpName                           // object name
  6. );

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

  1. #include "iostream"
  2. #include "windows.h"
  3. using namespace std;
  4. DWORD WINAPI ThreadProc1(LPVOID lpParam);
  5. DWORD WINAPI ThreadProc2(LPVOID lpParam);
  6. HANDLE hEvent = NULL;
  7. HANDLE hThread1 = NULL;
  8. HANDLE hThread2 = NULL;
  9. int main(int argc, char *args[])
  10. {
  11. hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)</span>; //使用手动重置为无信号状态,初始化时有信号状态
  12. //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态
  13. //if (SetEvent(hEvent))
  14. //{
  15. //  cout << "setEvent 成功" <<endl;
  16. //}
  17. hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);
  18. Sleep(200);
  19. hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);
  20. Sleep(200);
  21. if ( NULL == hThread1)
  22. {
  23. cout <<"create thread fail!";
  24. }
  25. //DWORD dCount = ResumeThread(hThread);
  26. //cout << LOWORD(dCount) << endl;
  27. return 0;
  28. }
  29. DWORD WINAPI ThreadProc1(LPVOID lpParam)
  30. {
  31. cout <<"in thread1@!"<<endl;
  32. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);
  33. if ( WAIT_OBJECT_0 == dReturn)
  34. {
  35. cout <<" thread1 signaled ! "<<endl;
  36. }
  37. cout <<"in thread1 --signal"<<endl;
  38. //SetEvent(hEvent);
  39. return 0;
  40. }
  41. DWORD WINAPI ThreadProc2(LPVOID lpParam)
  42. {
  43. cout <<"in thread2@!"<<endl;
  44. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);
  45. if ( WAIT_OBJECT_0 == dReturn)
  46. {
  47. cout <<"thread2 signaled ! "<<endl;
  48. }
  49. cout <<"in thread2--signal"<<endl;
  50. return 0;
  51. }

执行结果:

从结果中看,执行完线程1又执行了线程2.

由于hEvent = CreateEvent(NULL, TRUE, TRUE, NULL),使用手动重置为无信号状态,初始化时有信号状态

所以hEvent一直处于有信号状态,无论是线程1释放后,hEvent仍处于有信号状态,所以线程2正常执行了。

测试2:

bManualReset:FALSE

bInitialState:TRUE

  1. hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

example2.cpp

  1. #include "iostream"
  2. #include "windows.h"
  3. using namespace std;
  4. DWORD WINAPI ThreadProc1(LPVOID lpParam);
  5. DWORD WINAPI ThreadProc2(LPVOID lpParam);
  6. HANDLE hEvent = NULL;
  7. HANDLE hThread1 = NULL;
  8. HANDLE hThread2 = NULL;
  9. int main(int argc, char *args[])
  10. {
  11. //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态
  12. hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); </span>//当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态
  13. //if (SetEvent(hEvent))
  14. //{
  15. //  cout << "setEvent 成功" <<endl;
  16. //}
  17. hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);
  18. Sleep(200);
  19. hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);
  20. Sleep(200);
  21. if ( NULL == hThread1)
  22. {
  23. cout <<"create thread fail!";
  24. }
  25. //DWORD dCount = ResumeThread(hThread);
  26. //cout << LOWORD(dCount) << endl;
  27. return 0;
  28. }
  29. DWORD WINAPI ThreadProc1(LPVOID lpParam)
  30. {
  31. cout <<"in thread1@!"<<endl;
  32. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);
  33. if ( WAIT_OBJECT_0 == dReturn)
  34. {
  35. cout <<" thread1 signaled ! "<<endl;
  36. }
  37. cout <<"in thread1 --signal"<<endl;
  38. //SetEvent(hEvent);
  39. return 0;
  40. }
  41. DWORD WINAPI ThreadProc2(LPVOID lpParam)
  42. {
  43. cout <<"in thread2@!"<<endl;
  44. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);
  45. if ( WAIT_OBJECT_0 == dReturn)
  46. {
  47. cout <<"thread2 signaled ! "<<endl;
  48. }
  49. cout <<"in thread2--signal"<<endl;
  50. return 0;
  51. }

执行结果:

从执行结果中分析,执行了线程1,线程2一直在等待,直到主线程结束。

由于hEvent = CreateEvent(NULL, FALSE, TRUE, NULL),当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

初始执行线程1的时候,hEvent是有信号的,所以线程1正常执行;又由于bManualReset=FALSE,所以执行完线程1后,hEven

  1. WaitForSingleObject(hEvent,INFINITE);

函数一直在等待hEvent变为有信号状态,但是当主线程执行完,还没等待到,线程2程序一直没有走下去。

测试3:

bManualReset:TRUE
bInitialState:FALSE

hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态

example3.cpp

  1. #include "iostream"
  2. #include "windows.h"
  3. using namespace std;
  4. DWORD WINAPI ThreadProc1(LPVOID lpParam);
  5. DWORD WINAPI ThreadProc2(LPVOID lpParam);
  6. HANDLE hEvent = NULL;
  7. HANDLE hThread1 = NULL;
  8. HANDLE hThread2 = NULL;
  9. int main(int argc, char *args[])
  10. {
  11. //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态
  12. //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态
  13. hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态</span>
  14. //if (SetEvent(hEvent))
  15. //{
  16. //  cout << "setEvent 成功" <<endl;
  17. //}
  18. hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);
  19. Sleep(200);
  20. hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);
  21. Sleep(200);
  22. if ( NULL == hThread1)
  23. {
  24. cout <<"create thread fail!";
  25. }
  26. //DWORD dCount = ResumeThread(hThread);
  27. //cout << LOWORD(dCount) << endl;
  28. return 0;
  29. }
  30. DWORD WINAPI ThreadProc1(LPVOID lpParam)
  31. {
  32. cout <<"in thread1@!"<<endl;
  33. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);
  34. if ( WAIT_OBJECT_0 == dReturn)
  35. {
  36. cout <<" thread1 signaled ! "<<endl;
  37. }
  38. cout <<"in thread1 --signal"<<endl;
  39. //SetEvent(hEvent);
  40. return 0;
  41. }
  42. DWORD WINAPI ThreadProc2(LPVOID lpParam)
  43. {
  44. cout <<"in thread2@!"<<endl;
  45. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);
  46. if ( WAIT_OBJECT_0 == dReturn)
  47. {
  48. cout <<"thread2 signaled ! "<<endl;
  49. }
  50. cout <<"in thread2--signal"<<endl;
  51. return 0;
  52. }

执行结果,可想而知,只能输出:
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

  1. #include "iostream"
  2. #include "windows.h"
  3. using namespace std;
  4. DWORD WINAPI ThreadProc1(LPVOID lpParam);
  5. DWORD WINAPI ThreadProc2(LPVOID lpParam);
  6. HANDLE hEvent = NULL;
  7. HANDLE hThread1 = NULL;
  8. HANDLE hThread2 = NULL;
  9. int main(int argc, char *args[])
  10. {
  11. //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态
  12. //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态
  13. //hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态
  14. hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态
  15. if (SetEvent(hEvent))
  16. {
  17. cout << "setEvent 成功" <<endl;
  18. }
  19. hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);
  20. Sleep(200);
  21. hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);
  22. Sleep(200);
  23. if ( NULL == hThread1)
  24. {
  25. cout <<"create thread fail!";
  26. }
  27. //DWORD dCount = ResumeThread(hThread);
  28. //cout << LOWORD(dCount) << endl;
  29. return 0;
  30. }
  31. DWORD WINAPI ThreadProc1(LPVOID lpParam)
  32. {
  33. cout <<"in thread1@!"<<endl;
  34. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);
  35. if ( WAIT_OBJECT_0 == dReturn)
  36. {
  37. cout <<" thread1 signaled ! "<<endl;
  38. }
  39. cout <<"in thread1 --signal"<<endl;
  40. //SetEvent(hEvent);
  41. return 0;
  42. }
  43. DWORD WINAPI ThreadProc2(LPVOID lpParam)
  44. {
  45. cout <<"in thread2@!"<<endl;
  46. DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);
  47. if ( WAIT_OBJECT_0 == dReturn)
  48. {
  49. cout <<"thread2 signaled ! "<<endl;
  50. }
  51. cout <<"in thread2--signal"<<endl;
  52. return 0;
  53. }

由于调用SetEvent,hEvent为有信号状态,线程1正常执行,又由于调用完线程1后,hEvent自动重置为无信号状态,所以线程2只能在等待,直到主线程退出。

修改:线程1中的SetEvent(hEvent);的注释去掉,再运行,则线程1和线程2 都会执行。

c++中CreateEvent函数的更多相关文章

  1. 线程中CreateEvent和SetEvent及WaitForSingleObject的用法

    首先介绍CreateEvent是创建windows事件的意思,作用主要用在判断线程退出,线程锁定方面. CreateEvent 函功能描述:创建或打开一个命名的或无名的事件对象. EVENT有两种状态 ...

  2. Oracle 中 decode 函数用法

    Oracle 中 decode 函数用法 含义解释:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译 ...

  3. mysql中now()函数的使用,还有oracle的sysdate,可能埋下的坑

    mysql中now()函数的使用,还有oracle的sysdate 在需求中如果系统中药添加当前操作的时间那么很简单的一个操作在写sql的时候直接在这个字段对应的位置写上now()函数就可以了,这样就 ...

  4. 程序代码中退出函数exit()与返回函数return ()的区别

    程序代码中退出函数exit()与返回函数return ()的区别   exit(0):正常运行程序并退出程序:   exit(1):非正常运行导致退出程序:   return():返回函数,若在主函数 ...

  5. mysql中find_in_set()函数的使用

    首先举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有 1头条.2推荐.3热点.4图文等等 .现在有篇文章他既是头条,又是热点,还是图文,type中以 1,3,4 的格式存储.那我 ...

  6. QT中使用函数指针

    想仿命令行,所以定义了一个类,让一个String 对应一个 function,将两者输入list容器. 类中定义了 QString commandStr; void (MainWindow::*com ...

  7. Bash 是如何从环境变量中导入函数的

    在上文中曾说到: 所谓的环境变量的真实面目其实就是个任意字符串 Bash 在启动时会将 environ 数组中包含 = 号的字符串导入成为自己的变量 Bash 在启动外部命令时会将自己内部标记为环境变 ...

  8. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  9. PHP中spl_autoload_register()函数的用法

    spl_autoload_register (PHP 5 >= 5.1.2) spl_autoload_register — 注册__autoload()函数 说明 bool spl_autol ...

随机推荐

  1. android studio 如何进行格式化代码 快捷键必备

    在Eclipse中,我们一般使用Ctrl+Shift+F来格式化代码,Android Studio中需要换成: Reformat code CTRL + ALT + L (Win) OPTION + ...

  2. 手写mybatis框架

    前言 很久没有更新mybatis的源码解析了,因为最近在将自己所理解的mybatis思想转为实践. 在学习mybatis的源码过程中,根据mybatis的思想自己构建了一个ORM框架 .整个代码都是自 ...

  3. Java8 Functional(函数式接口)

    Functional 函数式(Functional)接口 只包含一个抽象方法的接口,称为函数式接口. 你可以通过 Lambda 表达式来创建该接口的对象.(若 Lambda 表达式抛出一个受检异常(即 ...

  4. 数据库行转列的sql语句

    问题描述 假设有张学生成绩表(CJ)如下Name Subject Result张三 语文 80张三 数学 90张三 物理 85李四 语文 85李四 数学 92李四 物理 82 现在 想写 sql 语句 ...

  5. 【原创】Kuberneters-HelmV3.3.1入门介绍及实践

    一.为什么需要Helm? Kubernetes目前已成为容器编排的事实标准,随着传统架构向微服务容器化架构的转变,从一个巨大的单体的应用切分为多个微服务,每个微服务可独立部署和扩展,实现了敏捷开发和快 ...

  6. oracle之事务和锁

    Oracle的事务和锁(PPT-I-283-293) 10.1 什么是事务 必须具备以下四个属性,简称ACID 属性:原子性(Atomicity):  事务是一个完整的操作.事务的各步操作是不可分的( ...

  7. python中反射 getattr(对象,'方法')()和hasattr(对象,'方法')

    getattr(对象,'方法')():从一个对象里面找到里面的方法,,, 传了一个对象,再传一个字符串,就能找到这个字符串的方法 hasattr(对象,'方法') 判断这个对象里面有没有这个方法,返回 ...

  8. 【吴恩达课程使用】anaconda (python 3.7) win10安装 tensorflow 1.8 cpu版

    [吴恩达课程使用]anaconda (python 3.7) win10安装 tensorflow 1.8 目前tensorflow是只支持到python3.6的,anaconda最新版本已经到pyt ...

  9. sql.表值类型

    表值类型是在sql server 2008中新加入的功能,我个人觉得确实很有用,之前从没用过,自从来到现在的公司后学到很多东西,所以和大家分享一下. ------建表值类型语法------------ ...

  10. java.lang.NoSuchMethodError: org.springframework.util.Assert.isTrue(ZLjava/util/function/Supplier;)V

    spring-data-redis 2的版本只支持spring5和spring boot2+,建议降低spring-data-redis版本 <!-- redis --> <depe ...