线程同步之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 );
回调函数无需赘述。