Windows CEvent事件
2015-02-05 14:23 sylar_liang 阅读(1134) 评论(0) 编辑 收藏 举报头文件:
#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.\n",i);
}
}
void fnThread2(void *ptr)
{
MyCEvent *pEvent = (MyCEvent *)ptr;
for( int i = 0; i < 5; i++ )
{
printf("ThreadFunc2:%d\n", 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.\n",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\n", i); Sleep(1000); } m_event.Set(); return 0; }