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()
可以获知更多细节。