zoukankan      html  css  js  c++  java
  • 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)事件的初始状态设置。

     

    看下面代码: 

     

      1 // event.cpp : 定义控制台应用程序的入口点。
      2 //
      3 
      4 #include "stdafx.h"
      5 #include <wtypes.h>
      6 #include <iostream>
      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         else
    101         {
    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         else
    142         {
    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类型作为循环变量的不确定性问题继续完善的,加入了临界区控制全局变量的访问。

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

    备注5处:

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

     

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

  • 相关阅读:
    Python进程池
    Python进程间通信
    python编程中的if __name__ == 'main与windows中使用多进程
    Python进程-实现
    python进程join()函数理解
    python 进程池Pool
    python多进程打印字符,加锁(Lock加锁)
    python进程、多进程
    正则表达式统计字符串中数字的个数
    python 处理xml
  • 原文地址:https://www.cnblogs.com/poissonnotes/p/7681484.html
Copyright © 2011-2022 走看看