首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

c++中SetEvent跟ResetEvent的使用

2013-10-06 
c++中SetEvent和ResetEvent的使用关于事件  事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处

c++中SetEvent和ResetEvent的使用

关于事件
  事件(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)事件的初始状态设置。


看下面代码:
DWORD WINAPI ThreadProc(LPVOID lpParam);  DWORD WINAPI ThreadProc2(LPVOID lpParam);  DWORD g_dwThreadID;  DWORD g_dwThreadID2;  UINT g_nTickets = 300;  //int g_nTickets = 300;  //备注1HANDLE g_hEvent = NULL;  HANDLE g_hEvent1 = NULL; HANDLE g_hEvent2 = NULL; CRITICAL_SECTION g_cs;int ThreadCout = 0;int main()  {  cout << "Main thread is running." << endl;  InitializeCriticalSection(&g_cs);//初始化临界区HANDLE hHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &g_dwThreadID);  ThreadCout++;HANDLE hHandle2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, &g_dwThreadID2); ThreadCout++;//g_hEvent = CreateEvent(NULL, FALSE,  TRUE, NULL);  g_hEvent1 = CreateEvent(NULL, FALSE,  TRUE, NULL);  //备注5:g_hEvent1 = CreateEvent(NULL, TRUE,  TRUE, NULL);g_hEvent2 = CreateEvent(NULL, FALSE,  TRUE, NULL);//备注5:g_hEvent2 = CreateEvent(NULL, TRUE,  TRUE, NULL);ResetEvent(g_hEvent1);ResetEvent(g_hEvent2);SetEvent(g_hEvent1); while (TRUE){EnterCriticalSection(&g_cs);int nCount = ThreadCout;  LeaveCriticalSection(&g_cs);if (nCount == 0){cout << "Main thread is break." << endl; break;}}Sleep(1000);//备注4CloseHandle(hHandle);   CloseHandle(hHandle2);  DeleteCriticalSection(&g_cs);cout << "Main thread is end." << endl;system("pause");  return 0;  }  DWORD WINAPI ThreadProc(LPVOID lpParam)  {   // cout << "No." << g_dwThreadID << " thread is running." << endl;  while (TRUE)  {  WaitForSingleObject(g_hEvent1, INFINITE);  cout << "No.1 " << g_dwThreadID << " thread is running." << endl;  EnterCriticalSection(&g_cs);int temp= g_nTickets; LeaveCriticalSection(&g_cs);cout << "No.1 " << g_dwThreadID << " thread is temp." << endl; if (temp > 0)  {  Sleep(10);  //Sleep(1000)//备注2cout << "No.1-" << g_dwThreadID << " sell ticket : " << temp << endl; EnterCriticalSection(&g_cs);g_nTickets--;  LeaveCriticalSection(&g_cs);SetEvent(g_hEvent2); //ResetEvent(g_hEvent1);//备注6  }  else  {  cout << "No.1- break" << endl;//ResetEvent(g_hEvent1);//备注6SetEvent(g_hEvent2);//没有这个ThreadProc2不能终止//备注3break;  }  }  EnterCriticalSection(&g_cs);ThreadCout--;  LeaveCriticalSection(&g_cs);cout << "No.1- end" << endl;return 0;  }  DWORD WINAPI ThreadProc2(LPVOID lpParam)  {  // while (TRUE)  {  WaitForSingleObject(g_hEvent2, INFINITE);  cout << "No.2 " << g_dwThreadID2 << " thread is running." << endl;  EnterCriticalSection(&g_cs);int temp= g_nTickets; LeaveCriticalSection(&g_cs);if (temp > 0)  {  Sleep(10);  //Sleep(1000)//备注2cout << "No.2-" << g_dwThreadID2 << " sell ticket : " << temp << endl;  EnterCriticalSection(&g_cs);g_nTickets--;  LeaveCriticalSection(&g_cs);SetEvent(g_hEvent1); //ResetEvent(g_hEvent2);//备注6}  else  {  cout << "No.2- break" << endl;//ResetEvent(g_hEvent2);//备注6SetEvent(g_hEvent1);//同样的问题,没有这个ThreadProc不能终止//备注3break;  }  }  EnterCriticalSection(&g_cs);ThreadCout--;  LeaveCriticalSection(&g_cs);cout << "No.2- end" << endl;return 0;  }  


这个代码是接上一遍关于UINT类型作为循环变量的不确定性问题继续完善的,加入了临界区控制全局变量的访问。本文要说明的是SetEvent和ResetEvent的使用,这个要看备注5和备注6。备注5处:CreateEvent的第二个参数决定了是否需要手动调用ResetEvent,当为TRUE时,是需要手动调用,如果不调用,会怎么样呢?不调用,事件会处于一直有信号状态,即备注6处。当为FALSE时候,不需要手动调用,调用不调用,效果一样。把ResetEvent放在WaitForSingleObject前面也是很好的做法。


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



热点排行