相关函数
1. GetExitCodeThread
BOOL GetExitCodeThread(
HANDLE hThread, // handle to the thread
LPDWORD lpExitCode // termination status
);
如果线程已经结束, lpExitCode 将会取得线程的返回值, 如果还未结束, lpExitCode的值是STILL_ACTIVE。这并不是好方法,因为线程的返回可能就是STILL_ACTIVE, 而这时线程已经结束。这时一个busy loop操作, 浪费CPU时间, 不建议使用。
2. WaitForSingleObject
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
WaitForSingleObject( hThrd, INFINITE ); // 线程进入休眠等待状态, 减少CPU使用
当核心对象被激发时,会导致 WaitForSingleObject() 醒来。当线程正在执行时,线程对象处于未激发状态。当线程结束时,线程对象就被激发了。数个线程可以同时等待相同的线程 handle 。当该线程 handle 变成激发状态时,所有等待中的线程都会被唤醒。
3. WaitForMultipleObjects
DWORD WaitForMultipleObjects(
DWORD nCount,
CONST HANDLE *lpHandles, // 指向一个由对象 handles 所组成的数组。
// 这些handles 不需要为相同的类型。
BOOL bWaitAll,
DWORD dwMilliseconds
);
允许在同一时间等待一个以上的对象。必须将一个由 handles 组成的数组交给此函数,并指定要等待其中一个对象或是全部的对象。
bWaitAll, 如果此为 TRUE ,表示所有的 handles 都必须激发,此函数才得以返回。否则此函数将在任何一个handle 激发时就返回。
WaitForMultipleObjects() 的返回值有些复杂:
(1) 如果因时间终了而返回,则返回值是WAIT_TIMEOUT;
(2) 如果bWaitAll是TRUE,那么返回值将是WAIT_OBJECT_0;
(3 )如果bWaitAll是FALSE,那么将返回值减去WAIT_OBJECT_0,就表示数组中的哪一个handle被激发了(只能得到第一个被激发对象的索引);
(4) 如果等待的对象中有任何mutexes,那么返回值可能从WAIT_ABANDONED_0 到 WAIT_ABANDONED_0 + nCount - 1;
(5) 如果函数失败,它会传回 WAIT_FAILED. 这时候可以使用GetLastError()找出失败的原因
4. MsgWaitForMultipleObjects
GUI线程等待handle对象, 使用MsgWaitForMultipleObjects, 使得UI可以响应。
核心对象激发状态的意义
对象 | 说明 |
Thread(线程) | 当线程结束时,线程对象即被激发。当线程还在进行时,则对象处于未激发状态 。线程对象系由CreateThread() 或 CreateRem oteThread() 产生 |
Process(进程) | 当进程结束时,进程对象即被激发。当进程还在进行时则对象处于未激发状态 。CreateProcess()或OpenProcess()会传回一个进程对象的 handle |
Change Notification | 当一个特定的磁盘子目录中发生一件特别的变化时,此对象即被激发。此对象系由 FindFirstChangeNotification()产生 |
Console Input | 当 console 窗口的输入缓冲区中有数据可用时,此对象将处于激发状态。 CreateFile() 和 GetStdFile() 两函数可以获得 console handle |
Event | Event 对象的状态直接受控于应用程序所使用的三个Win32 函数: SetEvent()、 PulseEvent()、 ResetEvent()。CreateEvent() 和 OpenEvent() 都可以传回一个 eventobject handle 。 Event 对象的状态也可以被操作系统设定--如果使用于"overlapped"操作时 |
Mutex | 如果 mut ex 没有被任何线程拥有,它就是处于激发状态。一旦一个等待 mut ex 的函数返回了, mutex 也就自动重置为未激发状态。 CreateMutex() 和 OpenMutex()都可以获得一个 mutex handle |
Semaphore | Semaphore 有点像 mut ex,但它有个计数器,可以约束其拥有者(线程)的个数。当计数器内容大于 0 时,semaphore 处于激发状态,当计数器内容等于 0 时,semaphore 处 于 未 激 发 状 态 。 CreateSemaphore()和OpenSemaphore() 可以传回一个 semaphore handle |
一个主消息循环例子,内含 MsgWaitForMultipleObjects()
DWORD nWaitCount;
HANDLE hWaitArray[4];
BOOL quit;
int exitCode;
while (!quit)
{
MSG msg;
int rc;
rc = MsgWaitForMultipleObjects(
nWaitCount,
hWaitArray,
FALSE,
INFINITE,
QS_ALLINPUT);
if (rc == WAIT_OBJECT_0 + nWaitCount)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{ // Get Next message in queue
if (msg.message == WM_QUIT)
{
quit = TRUE;
exitCode = msg.wParam;
break;
} // end if
TranslateMessage(&msg);
DispatchMessage(&msg);
} // end while
}
else if (rc >= WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + nWaitCount)
{
int nIndex = rc - WAIT_OBJET_0;
// We now know that the handle at array position
// nIndex was signaled.
// We would have had to keep track of what those
// handle mean to decide what to do next.
}
else if (rc == WAIT_TIMEOUT)
{
// Timeout expired
}
else if (rc >= WAIT_ABANDONED_0 && rc < WAIT_ABANDONED_0 + nWaitCount)
{
int nIndex = rc - WAIT_ABANDONED_0;
// A thread died that owned a mutex
// More about this in Chapter 4
}
else
{
// Something went wrong
}
}