zoukankan      html  css  js  c++  java
  • Windows CEvent事件

    头文件:
    #include <afxmt.h>

    CEvent类的一个对象,表示一个“事件”.事件是一个允许一个线程在某种情况发生时,唤醒另外一个线程的同步对象。

    基本步骤:
    1. 创建CEvent实例
    2. 在启动线程A时,将该实例传入线程A
    3. 在线程A结束前,调用CEvent的SetEvent()成员
    4. 在启动线程B的前面,等待CEvent的实例句柄
    ::WaitForSingleObject(pEvent->m_hObject, INFINITE);

    CEvent(
    BOOL bInitiallyOwn /* = FALSE */ , // 用来指定事件对象初始状态是否为发信状态(默认值为未发信)
    BOOL bManualReset /* = FALSE */ , // 用来指定创建的事件对象是自动事件还是手动事件对象(默认值为自动事件对象)
    LPCTSTR lpszNAme /* = NULL */ , // 用来定义事件对象的名称,指定要创建的事件对象的名,如果该事件对象将跨进程使用,则此参数不能为NULL。
    LPSECURITY_ATTRIBUTES lpsaAttribute /* = NULL */ // 指向一个LPSECURITY_ATTRIBUTES结构的指针
    );

    CEvent类提供的三种方法
    SetEvent() // 设置事件为发信状态,并且释放所有等待的线程。
    // 人工事件,则CEvent类对象保持为有信号状态;
    // 自动事件,则在SetEvent()将事件设置为有信号状态后,CEvent类对象由系统自动重置为无信号状态,除非一个线程被释放。
    // 该函数执行成功,则返回非零值,否则返回零。
    PulseEvent() // 设置事件为发信状态,并释放其他正在等待的线程,然后把事件设置为未发信状态
    // 发送一个事件脉冲,该函数完成一系列操作后才返回。
    // 对于自动事件,PulseEvent()将事件设置为有信号状态,等待一个线程被释放,将事件重置为无信号状态,然后PulseEvent()返回;
    //

    ResetEvent() // 设置事件为未发信状态
    // 执行成功,返回非零值,否则返回非零。

    DWORD WaitForSingleObject(
    HANDLE hHandle,
    DWORD dwMilliseconds
    );
    // 自动事件,则当WaitForSingleObject(hHandle,INFINITE)返回时,自动把CEvent对象重置为无信号状态。
    // CEvent::SetEvent()把对象设置为有信号状态,释放等待的线程。
    // CEvent::ResetEvent()把对象设置为无信号状态,程序在WaitForSingleObject(hHandle,INFINITE)处等待。

    1.自动事件
    初始状态为未发信状态,可以用SetEvent使之变为发信状态。自动事件对象一次只能启动一个处于等待状态的线程。

    2.手工事件
    手工事件对象一旦用函数SetEvent设置为“发信”状态,就一直处于有效状态,除非又使用对象的成员函数PulseEvent或ResetEvent把它重新设置为“未发信”状态。
    所以手工事件对象被用来恢复多个处在等待状态线程的运行。
    CEvent eventObj(FALSE,TRUE);

    类设计:

    数据:
    HANDLE m_hEvent;
    函数:
    CEvent(LPSECURITY_ATTRIBUTES lpsaAttribute, BOOL bManualReset, BOOL bInitialState) // 构造函数
    CEvent(LPSECURITY_ATTRIBUTES lpsaAttribute, BOOL bManualReset, BOOL bInitialState, const str::sting &name)

    virtual ~CEvent() // 析构函数

    // 拷贝与赋值构造函数不做定义

    //CEvent(const CEvent& rhs) // 拷贝构造函数

    //CEvent & operator =(const CEvent& rhs) // 赋值构造函数

    //
    HANDLE GetEvent() const // 获取事件的句柄
    void Wait() const // 等待
    BOOL Wait(DWORD timeoutMullis) const // 等待
    void Reset() // 重置
    void Set() // 设置
    void Pulse() //

    // MyCEvent.h
    #pragma
    once #include “CommonHead.h”

    class MyCEvent { public: // 构造函数 MyCEvent(LPSECURITY_ATTRIBUTES lpsaAttribute /*= NULL*/, BOOL bManualReset /*= FALSE*/, BOOL bInitialState /*= FALSE*/); MyCEvent(LPSECURITY_ATTRIBUTES lpsaAttribute, BOOL bManualReset, BOOL bInitialState, const std::string &name); virtual ~MyCEvent(); // 析构函数 //MyCEvent(const MyCEvent& rhs); // 拷贝构造函数 //MyCEvent & operator =(const MyCEvent& rhs); // 赋值构造函数 // HANDLE GetEvent() const; // 获取事件的句柄 void Wait() const; // 等待 BOOL Wait(DWORD timeoutMullis) const; // 等待 void Reset(); // 重置 void Set(); // 设置 void Pulse(); // private: HANDLE m_hEvent; // 事件句柄 };
    // MyCEvent.cpp
    #include "MyCEvent.h"
    
    static HANDLE Create(LPSECURITY_ATTRIBUTES lpsaAttribute, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName);
    
    
    MyCEvent::MyCEvent(LPSECURITY_ATTRIBUTES lpsaAttribute, BOOL bManualReset, BOOL bInitialState)
    {
        m_hEvent = Create(lpsaAttribute, bManualReset, bInitialState, NULL);
    }
    
    MyCEvent::MyCEvent(LPSECURITY_ATTRIBUTES lpsaAttribute, BOOL bManualReset, BOOL bInitialState, const _tstring &name)
    {
        m_hEvent = Create(lpsaAttribute, bManualReset, bInitialState, name.c_str());
    }
    
    
    MyCEvent::~MyCEvent(void)
    {
    }
    
    //// 拷贝构造函数
    //MyCEvent::MyCEvent(const MyCEvent& rhs)
    //{
    //
    //}
    
    //// 赋值构造函数
    //MyCEvent & MyCEvent::operator =(const MyCEvent& rhs)
    //{
    //
    //}
    
    // 获取事件的句柄
    HANDLE MyCEvent::GetEvent() const
    {
        return m_hEvent;
    }
    
    // 等待
    void MyCEvent::Wait() const
    {
        Wait(INFINITE);
    }
    
    // 等待
    BOOL MyCEvent::Wait(DWORD timeoutMullis) const
    {
        BOOL bRet = TRUE;
        DWORD result = ::WaitForSingleObject(m_hEvent, timeoutMullis);
        if(result == WAIT_TIMEOUT)
        {
            bRet = FALSE;
        }
    
        return bRet;
    }
    
    // 重置
    void MyCEvent::Reset() 
    {
        ::ResetEvent(m_hEvent);
    }
    
    // 设置
    void MyCEvent::Set()
    {
        ::SetEvent(m_hEvent);
    }
    void MyCEvent::Pulse()
    {
        ::PulseEvent(m_hEvent);
    }
    
    HANDLE Create(LPSECURITY_ATTRIBUTES lpsaAttribute, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName)
    {
        HANDLE hEvent = CreateEvent(lpsaAttribute, bManualReset, bInitialState, lpName);
        if(hEvent == NULL)
            return NULL;
        else
            return hEvent;
    }

    简单例子:
    #include <afxmt.h>

    void fnThread1(void *ptr)
    {
      MyCEvent *pEvent = (MyCEvent *)ptr;
      WaitForSingleObject(pEvent->GetEvent(), INFINITE);

      for(int i=0; i<10; ++i)
      {
        printf("Thread1 %d. ",i);
      }
    }

    void fnThread2(void *ptr)
    {
      MyCEvent *pEvent = (MyCEvent *)ptr;
      for( int i = 0; i < 5; i++ )
      {
        printf("ThreadFunc2:%d ", i);
        Sleep(1000);
      }

      pEvent->Set();
    }

    int _tmain(int argc, _TCHAR* argv[])
    {
      MyCEvent event(NULL, NULL, NULL);
      // 或者
      //MyCEvent event(NULL, TRUE, TRUE);
      //event.Reset();

      DWORD thread[2];

      ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fnThread1,(LPVOID)&event,0,&thread[0]);
      ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)fnThread2,(LPVOID)&event,0,&thread[1]);

      getchar();
      return 0;
    }

    // 包含之前定义的线程类,线程池一起使用的例子:

    int _tmain(int argc, _TCHAR* argv[])
    {
        MyCEvent event(NULL, FALSE, FALSE);
        // 或下面的方式调用
        //MyCEvent event(NULL, TRUE, TRUE);
        //event.Reset();
    
        MyThreadPool tpool;
        CThreadTest *mythread1 = new CThreadTest(event);
        tpool.AddThread(mythread1, false);
    
        CThreadTest2 *mythread2 = new CThreadTest2(event);
        tpool.AddThread(mythread2, false);
        
        getchar();
        return 0;    
    }
    
    // 派生的线程类
    // CThreadTest.h
    #pragma once
    #include "mythread.h"
    
    
    class MyCEvent;
    
    class CThreadTest :
        public MyThread
    {
    public:
        CThreadTest(MyCEvent & ev);
        ~CThreadTest(void);
    
        void endThread();
        DWORD run();
    
        MyCEvent & m_event;
    };
    
    // CThreadTest.cpp
    #include "ThreadTest.h"
    #include "MyCEvent.h"
    
    CThreadTest::CThreadTest(MyCEvent & ev)
        :m_event(ev)
    {
    }
    
    CThreadTest::~CThreadTest(void)
    {
    }
    
    void CThreadTest::endThread()
    {
        m_event.Set();
        WaitForSingleObject(m_event.GetEvent(),INFINITE);
    }
    
    DWORD CThreadTest::run()
    {
        WaitForSingleObject(m_event.GetEvent(), INFINITE);
    
        for(int i=0; i<10; ++i)
        {
            printf("Thread1 %d.
    ",i);
        }
    
        return 0;
    }
    
    // ThreadTest2.h 与 ThreadTest.h 一致
    // ThreadTest2.cpp
    #include "ThreadTest2.h"
    #include "MyCEvent.h"
    
    CThreadTest2::CThreadTest2(MyCEvent & ev)
        :m_event(ev)
    {
    }
    
    CThreadTest2::~CThreadTest2(void)
    {
    }
    
    void CThreadTest2::endThread()
    {
        m_event.Set();
        WaitForSingleObject(m_event.GetEvent(),INFINITE);
    }
    
    DWORD CThreadTest2::run()
    {
        for( int i = 0; i < 5; i++ )  
        {  
            printf("ThreadFunc2:%d
    ", i);  
            Sleep(1000);  
        } 
    
        m_event.Set();
        return 0;
    }
  • 相关阅读:
    C++笔记
    mongodb文件损坏的恢复--无可恢复数据
    wiredtiger--初学数据恢复
    mongodb异常恢复
    守护进程,互斥锁, IPC ,Queue队列,生产消费着模型
    进程,多进程,进程与程序的区别,程序运行的三种状态,multiprocessing模块中的Process功能,和join函数,和其他属性,僵尸与孤儿进程
    socket之UDP协议,并发编程介绍,操作系统发展史
    半连接数,粘包问题,自定义报头
    socket模块
    网络编程介绍,C/S 架构,网络通讯协议,osi七层
  • 原文地址:https://www.cnblogs.com/sylar-liang/p/4274739.html
Copyright © 2011-2022 走看看