CEvent

CEvent
2006-10-18 23:21
CEvent 类提供了对事件的支持。事件是一个允许一个线程在某种情况发生时,唤醒另外一个线程的同步对象。事件告诉线程何时去执行某一给定的任务,从而使多个线程流平滑。例如在某些网络应用程序中,一个线程(记为A)负责监听通信端口,另一个线程(记为B)负责更新用户数据。通过使用CEvent类,线程A可以通知线程B何时更新用户数据,这样线程B可以尽快地更新用户数据。每一个CEvent对象可以有两种状态:有信号状态(signaled)和无信号状态(nonsignaled)。线程监视位于其中的CEvent类对象的状态,并在相应的时候采取相应的操作。
    在MFC中,CEvent类对象有两种类型,分别是所谓的人工事件和自动事件。对于自动事件,当其获得信号后,就会释放下一个可用的线程。一个自动 CEvent对象在被至少一个线程释放后会自动返回到无信号状态;而人工事件对象获得信号后,释放所有可利用线程,直到调用成员函数ReSetEvent ()将其设置为无信号状态时为止。注意,在创建CEvent类的对象时,默认创建的是自动事件。

CEvent的各成员函数的原型与参数说明如下。
CEvent(BOOL bInitiallyOwn = FALSE,
BOOL bManualReset = FALSE,
LPCTSTR lpszName = NULL,
LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );
bInitiallyOwn:若bInitiallyOwn为TRUE,则使CMultilock类对象和CSingleLock类对象的线程可用;否则,要访问资源的线程必须等待。该参数的默认值为FALSE。
bManualReset:指定要创建的CEvent对象是属于手工事件还是自动事件。为TRUE,则为手工事件,否则为自动事件。该参数默认值为FALSE。
lpszName:指定要创建的事件对象的名,如果该事件对象将跨进程使用,则此参数不能为NULL。如果该参数和一个已经存在的CEvent对象相同,则该构造函数返回一个对这个已存在对象的引用;如果参数和一个已存在的非CEvent类的同步对象(如CMutex)相同,则对象创建失败;
lpsaAttribute:指向SECURITY_ATTRIBUTES结构的指针,该参数决定要创建的事件对象的安全属性,一般置为NULL。
在事件对象建成后,可以调用其成员函数来改变其状态。
BOOL CEvent::SetEvent ();
将CEvent类对象的状态设置为有信号状态,并且释放所有等待的线程;如果该事件是人工事件,则CEvent类对象保持为有信号状态,直到调用成员函数ResetEvent()将其重新设为无信号状态时为止,这样该事件就可以释放多个线程;如果CEvent类对象为自动事件,则在SetEvent()将事件设置为有信号状态后,CEvent类对象由系统自动重置为无信号状态,除非一个线程被释放。
如果该函数执行成功,则返回非零值,否则返回零。
BOOL CEvent::ResetEvent();
该函数将事件的状态设置为无信号状态,并保持该状态直至SetEvent()被调用时为止。由于自动事件是由系统自动重置,故自动事件不需要调用该函数。
如果该函数执行成功,返回非零值,否则返回非零。
BOOL CEvent::PulseEvent()
发送一个事件脉冲,该函数完成一系列操作后才返回。对于自动事件,PulseEvent()将事件设置为有信号状态,等待一个线程被释放,将事件重置为无信号状态,然后PulseEvent()返回;对于人工事件,则将等待该事件的所有线程被释放,事件被自动重置为无信号状态,然后PulseEvent()返回。
一个CEvent对象在线程中被创建后,自动处于无信号状态,但在另一个线程中可以调用Win32 API WaitForSingleObject()函数来监视其状态。
该函数的原型及参数说明如下:
DWORD WaitForSingleObject(HANDLE hHandle DWORD dwMilliseconds);
其中hHandle为指向要监视的同步对象的句柄,dwMilliseconds为监视hHandle所指向的对象所设置的超时值,单位为毫秒。当在线程的执行函数中调用该函数时,线程暂时挂起,系统监视hHandle所指向的对象的状态。如果经过dwMilliseconds毫秒后,hHandle指向的对象变为有信号状态,则WaitForSingleObject()返回,线程被释放,且返回值为WAIT_TIMEOUT;如果在挂起的dwMilliseconds毫秒内,线程所等待的对象在某一时刻变为有信号,则该函数立即返回,返回值为WAIT_OBJECT_0。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。
如果CEvent对象为自动事件,则当WaitForSingleObject(hHandle,INFINITE)返回时,自动把CEvent对象重置为无信号状态。CEvent::SetEvent()把对象设置为有信号状态,释放等待的线程。CEvent::ResetEvent()把对象设置为无信号状态,程序在WaitForSingleObject(hHandle,INFINITE)处等待。
CreateEvent
2006-10-18 23:35
HANDLE   CreateEvent(  
      LPSECURITY_ATTRIBUTES   lpEventAttributes,   //   SD  
      BOOL   bManualReset,                                               //   reset   type  
      BOOL   bInitialState,                                             //   initial   state  
      LPCTSTR   lpName                                                       //   object   name  
  );  
  该函数创建一个Event同步对象,并返回该对象的Handle  
   
  lpEventAttributes   一般为NULL  
  bManualReset             创建的Event是自动复位还是人工复位   ,如果true,人工复位,  
  一旦该Event被设置为有信号,则它一直会等到ResetEvent()API被调用时才会恢复  
  为无信号.   如果为false,Event被设置为有信号,则当有一个wait到它的Thread时,  
  该Event就会自动复位,变成无信号.  
  bInitialState           初始状态,true,有信号,false无信号  
  lpName                         Event对象名  
   
  一个Event被创建以后,可以用OpenEvent()API来获得它的Handle,用CloseHandle()  
  来关闭它,用SetEvent()或PulseEvent()来设置它使其有信号,用ResetEvent()  
  来使其无信号,用WaitForSingleObject()或WaitForMultipleObjects()来等待  
  其变为有信号.  
   
  PulseEvent()是一个比较有意思的使用方法,正如这个API的名字,它使一个Event  
  对象的状态发生一次脉冲变化,从无信号变成有信号再变成无信号,而整个操作是原子的.  
  对自动复位的Event对象,它仅释放第一个等到该事件的thread(如果有),而对于  
  人工复位的Event对象,它释放所有等待的thread.  
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用 `CEvent` 的示例代码: ```c++ class CMyWnd : public CWnd { public: CMyWnd(); // 定义 CEvent 对象 CEvent m_Event; // 定义线程函数 static UINT MyThread(LPVOID pParam); // 定义启动线程的函数 void StartMyThread(); DECLARE_MESSAGE_MAP() }; CMyWnd::CMyWnd() { // 创建事件对象 m_Event.Create(NULL, FALSE, FALSE, NULL); } BEGIN_MESSAGE_MAP(CMyWnd, CWnd) END_MESSAGE_MAP() UINT CMyWnd::MyThread(LPVOID pParam) { CMyWnd* pWnd = reinterpret_cast<CMyWnd*>(pParam); // 等待事件 DWORD dwResult = WaitForSingleObject(pWnd->m_Event.m_hObject, INFINITE); // 在这个函数中处理线程任务 // ... return 0; } void CMyWnd::StartMyThread() { // 创建线程 AfxBeginThread(MyThread, this); } ``` 在上面的示例代码中,我们定义了一个名为 `CMyWnd` 的窗口类,并声明了一个 `CEvent` 对象 `m_Event`。在类的构造函数中,我们使用 `Create` 函数创建了这个事件对象。然后,我们定义了一个线程函数 `MyThread`,在这个函数中,我们等待 `m_Event` 事件的触发,并在触发后处理线程任务。最后,我们定义了一个 `StartMyThread` 函数,用于创建线程并启动线程函数 `MyThread`。 在使用 `CEvent` 的方法中,我们通常会在一个线程中等待事件的触发,而在另一个线程中触发这个事件。例如,在主线程中可以调用 `StartMyThread` 函数来创建并启动一个新的线程,而在其他地方可以调用 `m_Event.SetEvent()` 函数来触发事件,从而使得线程可以继续执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值