Win32多线程 -- 判断线程结束

本文详细介绍了Windows API中的GetExitCodeThread、WaitForSingleObject、WaitForMultipleObjects和MsgWaitForMultipleObjects等函数,重点讲解了如何高效管理线程和核心对象的唤醒,以及它们在GUI线程交互中的应用,帮助理解对象激发状态在程序控制中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相关函数

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
SemaphoreSemaphore 有点像 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
 	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值