一、复习第二章
在第二章中,讲到了两种等待线程的技术:
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
等待多个线程结束:WaitForMultipleObjects
等待多个线程结束或消息到达:MsgWaitForMultipleObjects