一、复习第二章
在第二章中,讲到了两种等待线程的技术:
1)使用Sleep()函数——问题是你不可能事先知道什么事情要等待多久
2)使用busy loop,通过不断地调用GetExitCodeThread()这个函数来判断一个线程是否还在执行——问题是使用这个方法,必须持续不断的调用GetExitCodeThread(),直到其结果不再是STILL_ACTIVE,这方法不好,很浪费cpu时间,称为忙等待(busy waits)。
for ( ; ; ) { int rc; rc = GetExitCodeThread(hThrd,&exitCode); if (!rc && exitCode != STILL_ACTIVE) break; }
那么我们该怎么办?
二、另外一种有效的方法
使用WaitForSingleObject(hHandle,dwMilliseconds);
功能:某一线程中调用这个函数,此线程会被挂起,
1)dwMilliseconds毫秒内,如果此线程所等待的对象(hHandle所指线程)变成有信号状态(被激发,即hHandle线程结束),则该函数立即返回执行函数下面的代码;
2)超过dwMilliseconds毫秒,hHandle所指的对象还没有变成有信号状态,照样返回。
三、等待多个对象
先看一个实在的例子:
//参考书上例子 //程序的目的:只用个线程 ,完成件事 int main() { HANDLE hThrds[3]; int slot = 0; for( int I=1 ; I<=6 ; I++){ if( I > 3 ){ //已经存在个线程了 //等待其中的一个线程线束后,再创建线程做剩余的事情 //效率不高,因为线程结束的次序与它们被产生的次序不同 WaitForSingleObject( hThrds[slot] , INFINITE ) ; CloseHandle ( hThrds[slot] ); } //构造线程 hThrds[slot] = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL); if (++slot>2) slot=0; } for ( slot=0; slot<3; slot++){ //等待剩余的线程结束 WaitForSingleObject( hThrds[slot] , INFINITE ); CloseHandle ( hThrds[slot] ); } }
上面的这段程序有一个问题,就是效率不是很高;理想的状况是,一旦有一个线程结束,就立刻产生一个线程补上。仔细读上面的程序,你会发现它无法实现理想的状况;因为它假设线程结束的次序会和它们被产生的次序相同。比如,当依序产生了1,2,3线程以后,一定是按1,2,3的次序结束。其实不然,也许2比1更早结束。在这时,上面的程序并不会立刻产生一个线程填补2,而是非要等1结束了,才产生线程。那么能够实现理想的状况吗?答案是可以,请用WaitForMultipleObjects() 函数,
这个函数的用法基本上与WaitForSingleObject()差不多,在这里我就不举例说明了。
这个函数的用法基本上与WaitForSingleObject()差不多,在这里我就不举例说明了。
总结:
等待线程结束:WaitForSingleObject
等待多个线程结束:WaitForMultipleObjects
等待多个线程结束或消息到达:MsgWaitForMultipleObjects