最近使用到Event,做一下總結。
1、對象的創建:
創建了一個匿名的初始狀態爲“無信號”狀態的Event。
HANDLE _hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
2、信號狀態切換:
::SetEvent(_hEvent); // 設置爲有信號狀態.
::ResetEvent(_hEvent); // 設置爲無信號狀態.
DWORD dwRet = 0;
int time_ms = 100;
dwRet = ::WaitForSingleObject(_hEvent, INFINITE);
dwRet = ::WaitForSingleObject(_hEvent, 0);
dwRet = ::WaitForSingleObject(_hEvent, time_ms);
可以使用::WaitForSingleObject來查詢信號狀態。當第二個參數爲INFINITE時,將一直等待,直到Event變爲有狀態。當第二個參數爲0時,只是即時查詢Event的狀態並立即返回。當第二個參數爲其他時間時,除非超時或者Event變爲有狀態才返回。
當dwRet爲WAIT_OBJECT_0時,表示信號變爲有狀態。若dwRet爲WAIT_TIMEOUT,表示超時。
4、使用示例
我們用一個使用示例來看看Event的用法。比如我們有三塊緩存或者文件,需要在整個程序運行過程中每隔1000ms保存一次。如下:
class CMyRawFile
{
public:
void Save();
// ...
};
class CConfigFileMgr
{
public:
CConfigFileMgr() : m_hEvent(NULL), m_hThread(NULL)
{
unsigned int id = 0;
m_hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
m_hThread = (HANDLE)_beginthreadex(NULL, 0, _Thread_Proc, (void*)this, 0, &id);
if (m_hThread)
{
::WaitForSingleObject(m_hThread, 10);
}
}
~CConfigFileMgr()
{
if (m_hThread)
{
if (m_hEvent)
{
::SetEvent(m_hEvent);
}
::WaitForSingleObject(m_hThread, INFINITE);
::CloseHandle(m_hThread);
m_hThread = NULL;
}
if (m_hEvent)
{
::CloseHandle(m_hEvent);
m_hEvent = NULL;
}
}
static unsinged __stdcall _Thread_Proc(void* pParam)
{
CConfigFileMgr* pThis = (CConfigFileMgr*)pParam;
if (!pThis)
{
return 0;
}
while (true)
{
DWORD dwRet = ::WaitForSingleObject(m_hEvent, 1000);
if (dwRet == WAIT_OBJECT_0)
{
break;
}
else if (dwRet == WAIT_TIMEOUT)
{
pThis->m_sysConfig.Save();
pThis->m_usrConfig.Save();
pThis->m_cache.Save();
}
}
pThis->m_sysConfig.Save();
pThis->m_usrConfig.Save();
pThis->m_cache.Save();
_endthreadex(0);
return 0;
}
private:
HANDLE m_hEvent;
HANDLE m_hThread;
CMyRawFile m_sysConfig;
CMyRawFile m_usrConfig;
CMyRawFile m_cache;
};
因爲我們在初始創建Event時將信號狀態設爲FALSE,此後一直沒有變化,所以在_Thread_Proc線程函數中WaitForSingleObject一直在等待1000ms後返回WAIT_TIMEOUT,使得文件的保存操作得以調用。
當程序退出時,CConfigFileMgr對象需要析構,則調用SetEvent將信號設置爲有狀態,然後緊接着讓m_hThread對應的線程進入等待,這時_Thread_Proc又檢測到m_hEvent有信號,返回WAIT_OBJECT_0。使得死循環跳出,然後用_endthreadex結束線程。
最終關閉釋放所有HANDLE,整個程序結束。可以看出,_Thread_Proc函數實際上起到了一個定時器的效果。