DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
參數
hHandle 等待對象的 handle (代表一個核心對象)。在本
例中,此為線程 handle 。
dwMilliseconds 等待的最長時間。時間終了,即使 handle 尚未成
為激髮狀態,此函數還是要返回。此值可以是 0
(代表立刻返回),也可以是 INFINITE 代表無
窮等待。
傳回值
如果函數失敗,則傳回WAIT_FAILED。這時候你可調用 GetLastError() 取
得更多資訊。此函數的成功有三個因素:
1. 等待的目標(核心對象)變成激髮狀態。這種情況下傳回值將為
WAIT_OBJECT_0。
2. 核心對象變成激髮狀態之前,等待時間終了。這種情況下傳回值將為
WAIT_TIMEOUT。
3. 如果一個擁有 mu tex(互斥器)的線程結束前沒有釋放 mu tex,則傳
回 WAIT_ ABANDONED
關於 tim e-out ,有一個特別重要的用途,但很少被人注意。設定 tim e-out
為 0 ,使你能夠檢查 handle 的狀態並立刻返回,沒有片刻停留。如果 handle
已經備妥,那麼這個函數會成功並傳回 WAIT_OBJECT_0 。否則,這個函數
立刻返回並傳回 WAIT_TIMEOUT 。
另有其他一些理由使你需要設定 tim e-out 參數。最簡單的一個理由就是
你不希望被粘住,特別是在調試時。如果你所等待的線程進入了一個無窮循
環,你或許可以根據此函數的傳回值以及 tim e-out 終了與否,獲得一些警告。
WaitForSingleObject() 可以面對許多種 handles 工作,不一定要是本例所
使用的線程 handle 。事實上,Win32 中大部分以 HANDLE 表示的對象都能
夠作為 WaitForSingleO bject() 的等待目標。視你所擁有的對象不同,作業系統
等待的事情也不一樣。形式上來說,系統等待著這一對象“被激發”。
我曾經提過 Win32 的各種核心對象,如檔案、線程、互斥器
(Mutexes)等等。這些對象的狀態都可能是線程感興趣的東西。訊號量
(semaphores )和互斥器(mutexes)可記錄紅燈綠燈狀態,檔案對象可告訴我
們一個 I/O 操作何時完成,線程對象則一如所見,可以告訴我們它何時結束。
線程可以使用像 WaitForSingleO bject() 這樣的函數,有效地等待上述任
何情況發生。問題是,我們真正等待的到底是什嗎?
可被 WaitForSingleO bject() 使用的核心對象有兩種狀態:激發與未激
發。WaitForSingleObject() 會在目標物變成激髮狀態時返回。事實上我們也幾
乎是以此作為對象激發與否的操作型定義。
當核心對象被激發時,會導致WaitForSingleObject() 醒來。稍後你將看到的
其他 Wait() 函數也是如此。
當線程正在執行時,線程對象處於未激髮狀態。當線程結束時,線程對象
就被激發了。因此,任何線程如果等待的是一個線程對象,將會在等待對象結
束時被調用,因為當時線程對象自動變成激髮狀態。
數個線程可以同時等待相同的線程 handle 。當該線程 handle 變成激髮狀
態時,所有等待中的線程都會被喚醒。然而,其他核心對象可能只喚醒一個等
待中的線程。到底是哪一種行為,得視你等待什麼樣的對象而定。某些對象的
激髮狀態只能夠維持到一個等待中的線程被喚醒,其他對象的激髮狀態則或許
可以維持到它又被明白地重設(reset )。下一章你就會看到一個名為 EVENTTST
的程式,讓你實地體會一下線程如何應付激發對象。
WaitForMultipleObjects()
Win32 函數中的 WaitForMultipleObjects() 允許你在同一時間等待一個
以上的對象。你必須將一個由 handles 組成的數組交給此函數,並指定要等待
其中一個對象或是全部的對象。下面就是這個函數的原型:
DWORD WaitForMultipleObjects(
DWORD nCount,
CONST HANDLE *lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds
);
參數
nCount 表示 lpH andles 所指之 handles 數組的元素個
數。最大容量是 MAXIMUM_WAIT_OBJECTS 。
lpHandles 指向一個由對象 handles 所組成的數組。這些
handles 不需要為相同的類型。
bWaitAll 如果此為 TRUE ,表示所有的 handles 都必須激
發,此函數才得以返回。否則此函數將在任何一個
handle 激發時就返回。
dwMilliseconds 當該時間長度終了時,即使沒有任何 handles 激
發,此函數也會返回。此值可為 0 ,以便測試。亦
可指定為 INFINITE ,表示無窮等待。
傳回值
WaitForMultipleObjects() 的傳回值有些複雜。
如果因時間終了而返回,則傳回值是 WAIT_TIMEOUT ,類似
WaitForSingleObject()。
如果 bWaitAll 是 TRUE ,那麼傳回值將是 WAIT_OBJECT_0 。
如果 bWaitAll 是 FALSE ,那麼將傳回值減去 WAIT_OBJECT_0,就
表示數組中的哪一個 handle 被激發了。
如果你等待的對象中有任何 mu texes ,那麼傳回值可能從
WAIT_ABANDONED_0 到 WAIT_ABANDONED_0 + nCount - 1 。
如果函數失敗,它會傳回 WAIT_FAILED 。這時候你可以使用
GetLastError() 找出失敗的原因。
注意,handles 數組中的元素個數有上限,絕對不能夠超過
MAXIMUM_WAIT_OBJECTS。在 Windows NT 3.x 和 4.0 中,其值為 64(譯
註:在 Window s 95 中也一樣)。
利用 TerminateThread() 放棄一個線程
這正是 Win32 程式設計的一般性問題。我如何能夠安全地關閉任何執行
中的線程呢?最明顯的答案就是利用 Term inateThread():
BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode
);
參數
hThread 欲令其結束之線程的 handle 。該線程就是我們的
行動目標。
dwExitCode 該線程的結束代碼。
傳回值
如果函數成功,則傳回 TRUE 。如果失敗,則傳回 FALSE 。GetLastError()
可以獲知更多細節。