標籤:ase ica 連續 詳解 資料 init 標頭檔 而且 一個人
系統核心對象中的Event事件對象,在進程、線程間同步的時候是比較常用,發現它有兩個出發函數,一個是SetEvent,還有一個PulseEvent,
兩者的區別是:
SetEvent為設定事件對象為有訊號狀態;而PulseEvent也是將指定的事件設為有訊號狀態,
不同的是如果是一個人工重設事件,正在等候事件的、被掛起的所有線程都會進入活動狀態,函數隨後將事件設回,並返回;如果是一個 自動重設事件,則正在等候事件的、被掛起的單個線程會進入活動狀態,事件隨後設回無訊號,並且函數返回。
也就是說在自動重設模式下PulseEvent和SetEvent的作用沒有什麼區別,但在手動模式下PulseEvent就有明顯的不同,可以比較容易的控製程序是單步走,還是連續走。如果讓迴圈按要求執行一次就用PulseEvent,如果想讓迴圈連續不停的運轉就用SetEvent,在要求停止的地方發個ResetEvent就OK了。
臨界區的作用:避免臨界區內的資料(一般為共用的資源)被不同的線程同時訪問,實現線程的同步操作。保證只能由先進入臨界區的一個線程訪問結束後,其他線程才可以繼續訪問共用的資源。臨界區在使用時以CRITICAL_SECTION結構對象保護共用資源,並分別用EnterCriticalSection()和LeaveCriticalSection()函數去標識和釋放一個臨界區。所用到的CRITICAL_SECTION結構對象必須經過InitializeCriticalSection()的初始化後才能使用,而且必須確保所有線程中的任何試圖訪問此共用資源的代碼都處在此臨界區的保護之下。否則臨界區將不會起到應有的作用,共用資源依然有被破壞的可能。
以下為臨界區的使用方法:
*.h標頭檔:
#include <winbase.h>
CRITICAL_SECTION m_cs_test; ///< 定義一個臨界區對象
*.cpp源檔案使用方法:
在類的建構函式內初始化臨界區對象
//該函數必須在任何線程調用EnterCriticalSection函數之前被調用,否則結果將是很難預計的
::InitializeCriticalSection(&m_cs_test);
在類的虛構函數內釋放臨界區對象
::DeleteCriticalSection(&m_cs_test);
使用方法一:
在所需要使用的函數中開始鎖定:
CCriticalSectionLock lock(m_cs_test);
在函數生命期結束後會自動解鎖。
使用方法二:
//進入開始鎖定資料:保護共用資源只被一個線程調用
EnterCriticalSection(&m_cs_test);
...//do something you want to
//離開鎖定的資料:允許共用資源被其他的線程調用
LeaveCriticalSection(&m_cs_test);
注意:
在使用臨界區時,一般不允許其已耗用時間過長,只要進入臨界區的線程還沒有離開,其他所有試圖進入此臨界區的線程都會被掛起而進入到等待狀態,並會在一定程度上影響程式的運行效能。尤其需要注意的是不要將等待使用者輸入或是其他一些外界幹預的操作包含到臨界區。如果進入了臨界區卻一直沒有釋放,同樣也會引起其他線程的長時間等待。換句話說,在執行了EnterCriticalSection()語句進入臨界區後無論發生什麼,必須確保與之匹配的LeaveCriticalSection()都能夠被執行到。可以通過添加結構化異常處理代碼來確保LeaveCriticalSection()語句的執行。雖然臨界區同步速度很快,但卻只能用來同步本進程內的線程,而不可用來同步多個進程中的線程。
WaitForSingleObject函數:
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);
參數:
hHandle:指定對象或事件的控制代碼;
dwMilliseconds: 等待時間,以毫妙為單位,當超過等待時間時,此函數將返回。如果該參數設定為0,則該函數立即返回,如果設定為INFINITE,則該函數直到有訊號才返回。
傳回值:
如果此函數成功,該函數的返回之標識了引起該函數返回的事件。傳回值如下:
WAIT_ABANDONED(0x00000080L)
指定的對象是一個互斥對象,該對象沒有被擁有該對象的線程線上程結束前釋放。互斥對象的所有權被同意授予調用該函數的線程。互斥對象被設定成為無訊號狀態。
WAIT_OBJECT_0 (0x00000000L)
指定的對象出有有訊號狀態。
WAIT_TIMEOUT (0x00000102L)
超過等待時間,指定的對象處於無訊號狀態
如果失敗,返回 WAIT_FAILED;
在程式中,對每個線程時間做了控制!
HANDLE hThread1;
hThread1=CreateThread(NULL,0,DataHandle,(LPVOID)&d,0,NULL); //建立線程處理資料
if(WaitForSingleObject(hThread1,
1000 //時限
)!= WAIT_OBJECT_0)
{
WriteLog(logFile,"終止線程");
TerminateThread(hThread1,0);
}
事件函數SetEvent、PulseEvent與WaitForSingleObject詳解