c++中CreateEvent函数

c++中CreateEvent函数,第1张

c++中CreateEvent函数

参考: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 都会执行。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/585451.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存