• c++中CreateEvent函数


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

    函数原型:

    [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. }    


    执行结果:

    从结果中看,执行完线程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. }    

    执行结果:

    从执行结果中分析,执行了线程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;
    }

    执行结果:

    可见,线程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. }    

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

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

  • 相关阅读:
    大规模web服务读书笔记 狼
    MVC3如果虚拟目录中有点号,会导致静态文件404 狼
    CDN服务商和CDN常见问题 狼
    中文字段名,问题根源查询无聊话题。 狼
    NET下Session共享的几种实现方式 狼
    企业应用架构读书笔记与总结 狼
    Redis简单本机测试 狼
    你是否经历过这些,求如何继续才能提升 狼
    WinDbg配置和使用基础
    Python IDLE入门
  • 原文地址:https://www.cnblogs.com/MCSFX/p/13156775.html
Copyright © 2020-2023  润新知