線程同步之Win32API的Wait函數
Win32API中的Wait函數非常重要,很多同步都需要Wait函數的配合,Wait函數很多,常用的我就不贅述了,只對一些有用但不常用的函數做一些描述。
1.WaitForSingleObject
最常用的函數,不用多說了。對於信號燈和信號量,每用一次,信號量減一。
DWORD WaitForSingleObject( HANDLE hHandle, // handle to object DWORD dwMilliseconds // time-out interval );
2.WaitForSingleObjectEx
DWORD WaitForSingleObjectEx( HANDLE hHandle, // handle to object DWORD dwMilliseconds, // time-out interval BOOL bAlertable // alertable option );
基本上和WaitForSingleObject一致,所不同的在於WaitForSingleObjectEx =
WaitForSingleObject(,,FALSE),也就是說在參數爲TRUE的情況下可以進入線程告警狀態,
可以使用APC機制。
3.WaitForMultipleObjects
DWORD WaitForMultipleObjects( DWORD nCount, // number of handles in array CONST HANDLE *lpHandles, // object-handle array BOOL fWaitAll, // wait option DWORD dwMilliseconds // time-out interval );
和WaitForSingleObject不同之處,在於等待多個句柄,這應該是一個與的關係,即是所有的句柄
都需要處於發信號的狀態。
4.WaitForMultipleObjectsEx
DWORD WaitForMultipleObjectsEx( DWORD nCount, // number of handles in array CONST HANDLE *lpHandles, // object-handle array BOOL fWaitAll, // wait option DWORD dwMilliseconds, // time-out interval BOOL bAlertable // alertable option );這個不需要多說什麼了。
Note:現在介紹幾種返回值
WAIT_OBJECT_0:狀態處於發信號的狀態。最合理的結束方式。
WAIT_TIMEOUT:超時退出。
WAIT_ABANDONED:針對Mutex對象,就是在owner線程退出之前也沒有釋放Mutex。
WAIT_FAILED:出錯退出。需要使用GetLastErr.
下面的可以能有繞:
WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount – 1):
如果fWaitAll是TRUE,返回WAIT_OBJECT_0表示所有句柄都發了信號;
如果fWaitAll是FLASE,返回什麼就是第幾個句柄發了信號。
WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount – 1):
如果fWaitAll是TRUE,返回值WAIT_ABANDONED_0表示所有的線程發信號,至少一個線程退出;
如果fWaitAll是TRUE,至少一個線程退出,句柄就是返回值指的那個。
接着我們來看下面兩個函數,一起說了:
DWORD MsgWaitForMultipleObjects( DWORD nCount, // number of handles in array CONST HANDLE pHandles, // object-handle array BOOL fWaitAll, // wait option DWORD dwMilliseconds, // time-out interval DWORD dwWakeMask // input-event type );
DWORD MsgWaitForMultipleObjectsEx( DWORD nCount, // number of handles in array CONST HANDLE pHandles, // object-handle array DWORD dwMilliseconds, // time-out interval DWORD dwWakeMask, // input-event type DWORD dwFlags // wait options );
我感覺這和WaitForMultipleObjects最大的區別在於,前者可以繼續轉消息泵,
而後者能把消息泵都停掉了,所以肯定收不到消息了。
特別提醒,fWaitAll,只能設置成FALSE,謹慎啊。
DWORD SignalObjectAndWait( HANDLE hObjectToSignal, // handle to object to signal HANDLE hObjectToWaitOn, // handle to object to watch DWORD dwMilliseconds, // time-out interval BOOL bAlertable // alertable option );
向一個句柄發一個信號,接着等待另一個句柄,用起來很簡單,應該可用性很強。
最後說四個函數
BOOL RegisterWaitForSingleObject( PHANDLE phNewWaitObject, // wait handle HANDLE hObject, // handle to object WAITORTIMERCALLBACK Callback, // timer callback function PVOID Context // callback function parameter ULONG dwMilliseconds, // time-out interval ULONG dwFlags // options );
這個函數測試了很久,才稍微有點一點心得。首先,Event一定要設定成自動的,
我因爲這個問題吃盡苦頭,然後可以當一個線程池來用,但是還有一個問題,
如下:
BOOL UnregisterWait( HANDLE WaitHandle // wait handle );
BOOL UnregisterWaitEx( HANDLE WaitHandle, // wait handle HANDLE CompletionEvent // completion event );
這個函數在使用的時候需要保護句柄,呵呵,否則系統很生氣,後果很嚴重:)
建議使用INVALID_HANDLE_VALUE作爲第二個參數,它會等到任務結束後,才註銷。
VOID CALLBACK WaitOrTimerCallback( PVOID lpParameter, // thread data BOOLEAN TimerOrWaitFired // reason );
回調函數無需贅述。