在Win32环境下编写多线程应用程序,经常要用到事件对象Event,来进行线程同步。与其相关的一组API包括:CreateEvent,SetEvent,ResetEvent,WaitForSingleObject,和CloseHandle。关于这些API的功能以及参数意义等这里就不多说了。下边,我封装了一个事件对象类,以及测试代码。已由本人在VS2005环境下编译,测试通过。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129  | 
						//MyEvent.h #ifndef My_Event_Header #define My_Event_Header #include <iostream> #ifdef WIN32 #include <Windows.h> #endif using namespace std; //--------------------------------------------------------------- class CEventImpl { protected: 	/* 	 创建一个匿名事件对象 	`bAutoReset  true   人工重置 				 false  自动重置 	*/ 	CEventImpl(bool bManualReset);		 	/* 	 销毁一个事件对象 	*/ 	~CEventImpl(); 	/* 	 将当前事件对象设置为有信号状态 	 若自动重置,则等待该事件对象的所有线程只有一个可被调度 	 若人工重置,则等待该事件对象的所有线程变为可被调度 	*/ 	void SetImpl(); 	/* 	 以当前事件对象,阻塞线程,将其永远挂起 	 直到事件对象被设置为有信号状态 	*/ 	bool WaitImpl(); 	/* 	 以当前事件对象,阻塞线程,将其挂起指定时间间隔 	 之后线程自动恢复可调度 	*/ 	bool WaitImpl(long lMilliseconds); 	/* 	 将当前事件对象设置为无信号状态 	*/ 	void ResetImpl(); private: 	HANDLE h_Event; }; inline void CEventImpl::SetImpl() { 	if (!SetEvent(h_Event)) 	{ 		cout<<"cannot signal event"<<endl; 	} } inline void CEventImpl::ResetImpl() { 	if (!ResetEvent(h_Event)) 	{ 		cout<<"cannot reset event"<<endl; 	} } //--------------------------------------------------------------- class CMyEvent: private CEventImpl { public: 	CMyEvent(bool bManualReset = true); 	~CMyEvent(); 	void Set(); 	bool Wait(); 	bool Wait(long milliseconds); 	bool TryWait(long milliseconds); 	void Reset(); private: 	CMyEvent(const CMyEvent&); 	CMyEvent& operator = (const CMyEvent&); }; inline void CMyEvent::Set() { 	SetImpl(); } inline bool CMyEvent::Wait() { 	return WaitImpl(); } inline bool CMyEvent::Wait(long milliseconds) { 	if (!WaitImpl(milliseconds)) 	{ 		cout<<"time out"<<endl; 		return false; 	} 	else 	{ 		return true; 	} } inline bool CMyEvent::TryWait(long milliseconds) { 	return WaitImpl(milliseconds); } inline void CMyEvent::Reset() { 	ResetImpl(); } #endif  | 
					
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51  | 
						//MyEvent.cpp #include "MyEvent.h" CEventImpl::CEventImpl(bool bManualReset) { 	h_Event = CreateEvent(NULL, bManualReset, FALSE, NULL); 	if (!h_Event) 		cout<<"cannot create event"<<endl; } CEventImpl::~CEventImpl() { 	CloseHandle(h_Event); } bool CEventImpl::WaitImpl() { 	switch (WaitForSingleObject(h_Event, INFINITE)) 	{ 	case WAIT_OBJECT_0: 		return true; 	default: 		cout<<"wait for event failed"<<endl; 	} 	return false; } bool CEventImpl::WaitImpl(long lMilliseconds) { 	switch (WaitForSingleObject(h_Event, lMilliseconds + 1)) 	{ 	case WAIT_TIMEOUT: 		return false; 	case WAIT_OBJECT_0: 		return true; 	default: 		cout<<"wait for event failed"<<endl; 		return false; 	} } CMyEvent::CMyEvent(bool bManualReset): CEventImpl(bManualReset) { } CMyEvent::~CMyEvent() { }  | 
					
下边是测试代码
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88  | 
						// CEvent.cpp : 定义控制台应用程序的入口点。 // #include "MyEvent.h" #include <process.h> #define PRINT_TIMES 10 //创建一个人工自动重置事件对象 CMyEvent g_myEvent(true); int g_iNum = 0; //线程函数1 unsigned int __stdcall ThreadProc1(void *pParam) { 	for (int i = 0; i < PRINT_TIMES; i++) 	{ 		g_iNum++; 		cout<<"ThreadProc1 do print, Num = "<<g_iNum<<endl; 		//设置事件为有信号状态 		g_myEvent.Set(); 		Sleep(1000); 	} 	return (unsigned int)0; } //线程函数2 unsigned int __stdcall ThreadProc2(void *pParam) { 	bool bRet = false; 	while ( 1 ) 	{ 		if ( g_iNum >= PRINT_TIMES ) 		{ 			break; 		} 		//以当前事件对象阻塞本线程,将其挂起 		bRet = g_myEvent.Wait(); 		if ( bRet ) 		{ 			cout<<"ThreadProc2 do print, Num = "<<g_iNum<<endl; 			//设置事件为无信号状态 			g_myEvent.Reset(); 		} 		else 		{ 			cout<<"ThreadProc2 system exception"<<endl; 		} 	} 	return (unsigned int)0; } int main(int argc, char* argv[]) { 	HANDLE hThread1, hThread2; 	unsigned int uiThreadId1, uiThreadId2; 	//创建两个工作线程 	hThread1 = (HANDLE)_beginthreadex(NULL, 0, &ThreadProc1, NULL, 0, &uiThreadId1); 	hThread2 = (HANDLE)_beginthreadex(NULL, 0, &ThreadProc2, NULL, 0, &uiThreadId2); 	//等待线程结束 	DWORD dwRet = WaitForSingleObject(hThread1,INFINITE); 	if ( dwRet == WAIT_TIMEOUT ) 	{ 		TerminateThread(hThread1,0); 	} 	dwRet = WaitForSingleObject(hThread2,INFINITE); 	if ( dwRet == WAIT_TIMEOUT ) 	{ 		TerminateThread(hThread2,0); 	} 	//关闭线程句柄,释放资源 	CloseHandle(hThread1); 	CloseHandle(hThread2); 	system("pause"); 	return 0; }  | 
					
    测试代码中使用全局事件对象g_myEvent,对线程1和2进行同步,每当线程1函数对全局变量g_iNum做加1之后,通知线程2,立即将该变量值打印出来。如此循环10,线程1和2分别结束自己。
    编译,运行
Linux平台用C++实现事件对象,同步线程
发表评论
要发表评论,您必须先登录。