關於事件,先看MSDN介紹:
Event Objects
Anevent object is a synchronization object whose state can be explicitly set to signaled by use of theSetEvent
function.
即:Event與其他線程同步不同,Event可以通過函數來設置有無信號量。
初始化
A thread uses theCreateEvent or CreateEventEx function to create an event object. The creating thread specifies the initial state of the object and whether it is a manual-reset or auto-reset event object. The creating thread can also specify a name for the event object. Threads in other processes can open a handle to an existing event object by specifying its name in a call to theOpenEvent function.
HANDLE WINAPI CreateEvent(
__in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
__in BOOL bManualReset,
__in BOOL bInitialState,
__in_opt LPCTSTR lpName
);
HANDLE WINAPI CreateEventEx(
__in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
__in_opt LPCTSTR lpName,
__in DWORD dwFlags,
__in DWORD dwDesiredAccess
);
bManualReset :指定將事件對象創建成手動復原還是自動復原。如果是TRUE(wait functions恢復到無信號狀態),那麼必須用ResetEvent函數來手工將事件的狀態復原到無信號狀態。如果設置爲FALSE,當一個等待線程被釋放以後,系統將會自動將事件狀態復原爲無信號狀態。
bInitialState :指定初始化時是否爲有信號狀態,TRUE則有,FALSE則無。
The event object is useful in sending a signal to a thread indicating that a particular event has occurred.
事件對象是有用的在一個線程發送信號來表明一個特定的事件發生。
設置事件
Sets the specified event object to the signaled state.
BOOL WINAPI SetEvent(
__in HANDLE hEvent
);
即:讓事件變爲有信號狀態。
復位事件
Sets the specified event object to the nonsignaled state.
BOOL WINAPI ResetEvent(
__in HANDLE hEvent
);
即:讓事件變爲無信號狀態。
通過對事件對象進行操作,我們可以判斷一個特定事件是否發生,進行同步操作等。
測試代碼:
Event.h
#pragma once
#include <windows.h>
class ILock
{
public:
virtual void lock() = 0;
virtual void unlock() = 0;
};
class _CEvent : public ILock
{
public:
_CEvent();
~_CEvent();
virtual void lock();
virtual void unlock();
private:
HANDLE m_hEvent;
};
class CLock
{
public:
CLock(ILock&);
~CLock();
private:
ILock& m_lock;
};
Event.cpp
#include "stdafx.h"
#include "Event.h"
#include <assert.h>
_CEvent::_CEvent()
{
m_hEvent = ::CreateEvent(NULL, FALSE, TRUE, NULL);
assert(m_hEvent);
}
_CEvent::~_CEvent()
{
::CloseHandle(m_hEvent);
}
void _CEvent::lock()
{
WaitForSingleObject(m_hEvent, INFINITE);
}
void _CEvent::unlock()
{
SetEvent(m_hEvent);
}
CLock::CLock(ILock& locker) : m_lock(locker)
{
m_lock.lock();
}
CLock::~CLock()
{
m_lock.unlock();
}
test.cpp
// Event_test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <process.h>
#include "Event.h"
#define THREADCOUNT 10
_CEvent g_event;
int nFood = 0;
unsigned int WINAPI EatThread(void *pParam)
{
int i = (int)pParam;
int nHasEaten = 0;
while (true)
{
CLock lock(g_event);
if (nFood > 0)
{
Sleep(100);
std::cout << "消費者" << i << "進行消費,已經吃掉(" << ++nHasEaten << "),當前剩餘食物" << --nFood << std::endl;
}
else
{
break;
}
}
return 0;
}
unsigned int WINAPI ProductThread(void *pParam)
{
int i = 0;
while (i < 52)
{
std::cout << "生產者進行生產,當前剩餘食物" << ++nFood << std::endl;
i++;
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hProductThread;
HANDLE hEatThread[THREADCOUNT];
hProductThread = (HANDLE)_beginthreadex(NULL, 0, &ProductThread, (void *)0, 0, 0);
WaitForSingleObject(hProductThread, INFINITE);
for (int i = 0; i < THREADCOUNT; i++)
{
hEatThread[i] = (HANDLE)_beginthreadex(NULL, 0, &EatThread, (void *)i, 0, 0);
}
WaitForMultipleObjects(THREADCOUNT, hEatThread, TRUE, INFINITE);
::CloseHandle(hProductThread);
for (int i = 0; i < THREADCOUNT; i++)
{
::CloseHandle(hEatThread[i]);
}
system("pause");
return 0;
}