博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++中SetEvent和ResetEvent的使用
阅读量:4302 次
发布时间:2019-05-27

本文共 5097 字,大约阅读时间需要 16 分钟。

关于事件
  事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处于激发状态(signaled or true)或未激发状态(unsignal or false)。根据状态变迁方式的不同,事件可分为两类:
  (1)手动设置:这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。
  (2)自动恢复:一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。
  

创建事件的函数原型为:

 

HANDLE CreateEvent(

 LPSECURITY_ATTRIBUTES lpEventAttributes,
 // SECURITY_ATTRIBUTES结构指针,可为NULL
 BOOL bManualReset, 
 // 手动/自动
 // TRUE:在WaitForSingleObject后必须手动调用ResetEvent清除信号
 // FALSE:在WaitForSingleObject后,系统自动清除事件信号
 BOOL bInitialState, //初始状态
 LPCTSTR lpName //事件的名称
);

 

使用"事件"机制应注意以下事项:

  (1)如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;
  (2)事件是否要自动恢复;
  (3)事件的初始状态设置。

 

看下面代码: 

 

复制代码

1 // event.cpp : 定义控制台应用程序的入口点。  2 //  3   4 #include "stdafx.h"  5 #include 
6 #include
7 using namespace std; 8 9 DWORD WINAPI ThreadProc(LPVOID lpParam); 10 DWORD WINAPI ThreadProc2(LPVOID lpParam); 11 12 DWORD g_dwThreadID; 13 DWORD g_dwThreadID2; 14 15 UINT g_nTickets = 300; //int g_nTickets = 300; //备注1 16 17 HANDLE g_hEvent1 = NULL; 18 HANDLE g_hEvent2 = NULL; 19 20 CRITICAL_SECTION g_cs; 21 22 int ThreadCout = 0; 23 24 int _tmain(int argc, _TCHAR* argv[]) 25 { 26 cout << "Main thread is running." << endl; 27 28 InitializeCriticalSection(&g_cs);//初始化临界区 29 30 HANDLE hHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &g_dwThreadID); 31 ThreadCout++; 32 HANDLE hHandle2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, &g_dwThreadID2); 33 ThreadCout++; 34 35 g_hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL); //备注5:g_hEvent1 = CreateEvent(NULL, TRUE, TRUE, NULL); 36 g_hEvent2 = CreateEvent(NULL, FALSE, TRUE, NULL); //备注5:g_hEvent2 = CreateEvent(NULL, TRUE, TRUE, NULL); 37 38 ResetEvent(g_hEvent1); 39 ResetEvent(g_hEvent2); 40 41 SetEvent(g_hEvent1); 42 43 44 while (TRUE) 45 { 46 EnterCriticalSection(&g_cs); 47 int nCount = ThreadCout; 48 LeaveCriticalSection(&g_cs); 49 50 if (nCount == 0) 51 { 52 cout << "Main thread is break." << endl; 53 break; 54 } 55 56 } 57 58 59 Sleep(1000); //备注4 60 61 CloseHandle(hHandle); 62 CloseHandle(hHandle2); 63 64 DeleteCriticalSection(&g_cs); 65 66 cout << "Main thread is end." << endl; 67 68 system("pause"); 69 return 0; 70 } 71 72 73 DWORD WINAPI ThreadProc(LPVOID lpParam) 74 { 75 // cout << "No." << g_dwThreadID << " thread is running." << endl; 76 while (TRUE) 77 { 78 WaitForSingleObject(g_hEvent1, INFINITE); 79 cout << "No.1 " << g_dwThreadID << " thread is running." << endl; 80 81 EnterCriticalSection(&g_cs); 82 int temp = g_nTickets; 83 LeaveCriticalSection(&g_cs); 84 85 cout << "No.1 " << g_dwThreadID << " thread is temp." << endl; 86 87 if (temp > 0) 88 { 89 Sleep(10); //Sleep(1000) //备注2 90 cout << "No.1-" << g_dwThreadID << " sell ticket : " << temp << endl; 91 92 93 EnterCriticalSection(&g_cs); 94 g_nTickets--; 95 LeaveCriticalSection(&g_cs); 96 97 SetEvent(g_hEvent2); 98 //ResetEvent(g_hEvent1);//备注6 99 }100 else101 {102 cout << "No.1- break" << endl;103 //ResetEvent(g_hEvent1);//备注6 104 SetEvent(g_hEvent2);//没有这个ThreadProc2不能终止 //备注3 105 break;106 }107 }108 109 EnterCriticalSection(&g_cs);110 ThreadCout--;111 LeaveCriticalSection(&g_cs);112 cout << "No.1- end" << endl;113 114 return 0;115 }116 117 DWORD WINAPI ThreadProc2(LPVOID lpParam)118 {119 // 120 while (TRUE)121 {122 WaitForSingleObject(g_hEvent2, INFINITE);123 cout << "No.2 " << g_dwThreadID2 << " thread is running." << endl;124 125 EnterCriticalSection(&g_cs);126 int temp = g_nTickets;127 LeaveCriticalSection(&g_cs);128 129 if (temp > 0)130 {131 Sleep(10); //Sleep(1000) //备注2 132 cout << "No.2-" << g_dwThreadID2 << " sell ticket : " << temp << endl;133 134 EnterCriticalSection(&g_cs);135 g_nTickets--;136 LeaveCriticalSection(&g_cs);137 138 SetEvent(g_hEvent1);139 //ResetEvent(g_hEvent2);//备注6 140 }141 else142 {143 cout << "No.2- break" << endl;144 //ResetEvent(g_hEvent2);//备注6 145 SetEvent(g_hEvent1);//同样的问题,没有这个ThreadProc不能终止 //备注3 146 break;147 }148 }149 150 EnterCriticalSection(&g_cs);151 ThreadCout--;152 LeaveCriticalSection(&g_cs);153 154 cout << "No.2- end" << endl;155 return 0;156 }

复制代码

 

这个代码是接上一遍关于UINT类型作为循环变量的不确定性问题继续完善的,加入了临界区控制全局变量的访问。

本文要说明的是SetEvent和ResetEvent的使用,这个要看备注5和备注6。

备注5处:

CreateEvent的第二个参数决定了是否需要手动调用ResetEvent,当为TRUE时,是需要手动调用,如果不调用,会怎么样呢?不调用,事件会处于一直有信号状态,即备注6处。当为FALSE时候,不需要手动调用,调用不调用,效果一样。把ResetEvent放在WaitForSingleObject前面也是很好的做法。

 

转载请注明原创链接:http://blog.csdn.net/wujunokay/article/details/12272581

你可能感兴趣的文章
开源SoC整理
查看>>
【2020-3-21】Mac安装Homebrew慢,解决办法
查看>>
influxdb 命令行输出时间为 yyyy-MM-dd HH:mm:ss(年月日时分秒)的方法
查看>>
已知子网掩码,确定ip地址范围
查看>>
判断时间或者数字是否连续
查看>>
docker-daemon.json各配置详解
查看>>
Docker(一)使用阿里云容器镜像服务
查看>>
Docker(二) 基础命令
查看>>
Docker(三) 构建镜像
查看>>
Spring 全家桶注解一览
查看>>
JDK1.8-Stream API使用
查看>>
cant connect to local MySQL server through socket /tmp/mysql.sock (2)
查看>>
vue中的状态管理 vuex store
查看>>
Maven之阿里云镜像仓库配置
查看>>
Maven:mirror和repository 区别
查看>>
微服务网关 Spring Cloud Gateway
查看>>
SpringCloud Feign的使用方式(一)
查看>>
SpringCloud Feign的使用方式(二)
查看>>
关于Vue-cli+ElementUI项目 打包时排除Vue和ElementUI
查看>>
Vue 路由懒加载根据根路由合并chunk块
查看>>