c++中CreateEvent函数「建议收藏」

c++中CreateEvent函数「建议收藏」http://blog.csdn.net/chenyujing1234/article/details/8572921函数原型:[cpp] viewplain copyHANDLE CreateEvent(    LPSECURITY_ATTRIBUTES lpEventAttributes, // SD    BO

大家好,又见面了,我是你们的朋友全栈君。

http://blog.csdn.net/chenyujing1234/article/details/8572921

函数原型:

[cpp] 
view plain  
copy

  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

[cpp] 
view plain  
copy

  1. #include “iostream”    
  2. #include “windows.h”    
  3. using namespace std;    
  4.     
  5. DWORD WINAPI ThreadProc1(LPVOID lpParam);    
  6. DWORD WINAPI ThreadProc2(LPVOID lpParam);    
  7. HANDLE hEvent = NULL;    
  8. HANDLE hThread1 = NULL;    
  9. HANDLE hThread2 = NULL;    
  10. int main(int argc, char *args[])    
  11. {    
  12.     hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)</span>; //使用手动重置为无信号状态,初始化时有信号状态    
  13.     //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态    
  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.         
  34.     DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);    
  35.         
  36.     if ( WAIT_OBJECT_0 == dReturn)    
  37.     {    
  38.         cout <<” thread1 signaled ! “<<endl;    
  39.     }    
  40.     cout <<“in thread1 –signal”<<endl;    
  41.         
  42.     //SetEvent(hEvent);    
  43.     return 0;    
  44. }    
  45. DWORD WINAPI ThreadProc2(LPVOID lpParam)    
  46. {    
  47.     cout <<“in thread2@!”<<endl;    
  48.         
  49.     DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);    
  50.         
  51.     if ( WAIT_OBJECT_0 == dReturn)    
  52.     {    
  53.         cout <<“thread2 signaled ! “<<endl;    
  54.     }    
  55.     cout <<“in thread2–signal”<<endl;    
  56.         
  57.     return 0;    
  58. }    



执行结果:

c++中CreateEvent函数「建议收藏」


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

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

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


测试2:

bManualReset:FALSE
bInitialState:TRUE


[cpp] 
view plain  
copy

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



example2.cpp

[cpp] 
view plain  
copy

  1. #include “iostream”    
  2. #include “windows.h”    
  3. using namespace std;    
  4.     
  5. DWORD WINAPI ThreadProc1(LPVOID lpParam);    
  6. DWORD WINAPI ThreadProc2(LPVOID lpParam);    
  7. HANDLE hEvent = NULL;    
  8. HANDLE hThread1 = NULL;    
  9. HANDLE hThread2 = NULL;    
  10. int main(int argc, char *args[])    
  11. {    
  12.     //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态    
  13.     hEvent = CreateEvent(NULL, FALSE, TRUE, 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.         
  34.     DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);    
  35.         
  36.     if ( WAIT_OBJECT_0 == dReturn)    
  37.     {    
  38.         cout <<” thread1 signaled ! “<<endl;    
  39.     }    
  40.     cout <<“in thread1 –signal”<<endl;    
  41.         
  42.     //SetEvent(hEvent);    
  43.     return 0;    
  44. }    
  45. DWORD WINAPI ThreadProc2(LPVOID lpParam)    
  46. {    
  47.     cout <<“in thread2@!”<<endl;    
  48.         
  49.     DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);    
  50.         
  51.     if ( WAIT_OBJECT_0 == dReturn)    
  52.     {    
  53.         cout <<“thread2 signaled ! “<<endl;    
  54.     }    
  55.     cout <<“in thread2–signal”<<endl;    
  56.         
  57.     return 0;    
  58. }    

执行结果:

c++中CreateEvent函数「建议收藏」

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

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

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

[cpp] 
view plain  
copy

  1. WaitForSingleObject(hEvent,INFINITE);    



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


测试3:

bManualReset:TRUE
bInitialState:FALSE

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

example3.cpp

[cpp] 
view plain  
copy

  1. #include “iostream”    
  2. #include “windows.h”    
  3. using namespace std;    
  4.     
  5. DWORD WINAPI ThreadProc1(LPVOID lpParam);    
  6. DWORD WINAPI ThreadProc2(LPVOID lpParam);    
  7. HANDLE hEvent = NULL;    
  8. HANDLE hThread1 = NULL;    
  9. HANDLE hThread2 = NULL;    
  10. int main(int argc, char *args[])    
  11. {    
  12.     //hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态    
  13.     //hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态    
  14.     hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态</span>    
  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.         
  35.     DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);    
  36.         
  37.     if ( WAIT_OBJECT_0 == dReturn)    
  38.     {    
  39.         cout <<” thread1 signaled ! “<<endl;    
  40.     }    
  41.     cout <<“in thread1 –signal”<<endl;    
  42.         
  43.     //SetEvent(hEvent);    
  44.     return 0;    
  45. }    
  46. DWORD WINAPI ThreadProc2(LPVOID lpParam)    
  47. {    
  48.     cout <<“in thread2@!”<<endl;    
  49.         
  50.     DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);    
  51.         
  52.     if ( WAIT_OBJECT_0 == dReturn)    
  53.     {    
  54.         cout <<“thread2 signaled ! “<<endl;    
  55.     }    
  56.     cout <<“in thread2–signal”<<endl;    
  57.         
  58.     return 0;    
  59. }    

执行结果,可想而知,只能输出:


in thread1@! 

in thread2@! 

因为初始为无信号状态,所以hEvent一直处于无信号状态,因此这两个线程一直在等待,直到主线程结束。

修改:放开例子中的注释部分:

if (SetEvent(hEvent))//设置信号为有信号状态
{

cout << “setEvent 成功” <<endl;
}

执行结果:

c++中CreateEvent函数「建议收藏」


可见,线程1和线程2都执行了。

因为调用SetEvent,事件变为有信号状态,线程1执行;又由于线程1释放后,hEvent仍旧处于有信号状态,所以线程2也执行了。

再修改:在线程1中,添加ResetEvent(hEvent)(手动设置事件为无信号状态),则线程2不会执行。

测试4:

bManualReset:FALSE
bInitialState:FALSE

hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//线程释放后自动重置为无信号状态,初始化时为无信号状态

example4.cpp

[cpp] 
view plain  
copy

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

c++中CreateEvent函数「建议收藏」


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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/158701.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java技术介绍_Java技术汇总

    java技术介绍_Java技术汇总这篇文章总结了多年来使用Java的一些心得体会,主要是和一些Java基础知识点相关的,也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行业的准新手们,希望可以给大家一些经验,能让大家更好学习和使用Java。这次介绍的主要内容是和J2SE相关的部分,经过这么多年的Java开发,以及结合平时面试Java开发者的一些经验,J2SE方面主要就是要掌握以下的一些内容。1.JVM相关(包括了…

    2022年7月7日
    25
  • 让Web页面中的编辑器支持黏贴或直接拖拽来添加图片「建议收藏」

    让Web页面中的编辑器支持黏贴或直接拖拽来添加图片「建议收藏」让Web页面中的编辑器支持黏贴或直接拖拽来添加图片

    2022年4月21日
    49
  • 上海it外包公司排名_it外包公司排行榜怎么来的?

    上海it外包公司排名_it外包公司排行榜怎么来的?在我们平时上网的时候,总是看到在一些中介网站上会有一些IT外包公司排行榜,这些排行与其它行业的排行榜一样,指导着我们的选择,为我们的外包工作指出了一条相对明晰的道路。那到底这些网站上的排行准不准确呢?下面我们就为大家解析一下。1.名气和口碑。也许我们对外包行业不是很懂,但是在看其它行业如房地产,家电等与大众息息相关的产业时,就会发现但凡上榜的都是很有名气的,且口碑也很好。这就表明了排行还是比较…

    2022年6月14日
    46
  • MQTT服务器搭建与试用,桌面工具连接MQTT服务器

    MQTT服务器搭建与试用,桌面工具连接MQTT服务器简介MQTT(MessageQueuingTelemetryTransport,消息队列遥测传输)是IBM开发的一个即时通讯协议,它比较适合于在低带宽、不可靠的网络的进行远程传感器和控制设备通讯等,正在日益成为物联网通信协议的重要组成部分。MQTT现在主要用于即时通讯,物联网M2M,物联网采集等。本文就社区上常见的开源MQTT服务器在常见操作系统上的搭建做详细介绍。目前一些开源MQTT服…

    2022年5月29日
    42
  • python常用模块大全_python常用

    python常用模块大全_python常用mathmath.ceil(a):用来返回≥a的最小整数math.floor(a):用来返回≤a的最大整数round(a[,b])如果没有参数b,只有a,round()作用是四舍五入如果

    2022年7月28日
    3
  • 计算机二级考试数据结构与算法知识点_计算机二级算法与数据结构视频

    计算机二级考试数据结构与算法知识点_计算机二级算法与数据结构视频按照自己的理解写的解题思路,如有错误希望指正。1.算法的复杂度: ①时间复杂度:执行算法所需的计算工作量(又叫:基本运算次数) ②空间复杂度:执行算法所需的内存 它们是没有任何关系的!!!2.求二叉树序列类题目 要点:前序—根左右 中序—左根右 后序—左右根 例1:已知前序ABCDE,中序BCADE,求后序;同类型,已知任意两个求第三个 解题思路: 由前序知道A是根,结合中序,CB是左子树,DE…

    2022年8月18日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号