WIN32多线程程序设计学习笔记(第三章)

    技术2022-05-11  140

    WIN32多线程程序设计学习笔记(第三章)

     

    通过在上一章的学习,我学会使用GetExitCodeThread()这个函数来判断一个线程是否还在执行。通过这个函数,我就可以对付“某个线程必须在某个线程结束后才能运行”的情况。复习一下:

    程序片段:

                  for  ( ; ; )

                  {

                         int rc;

                         rc  =  GetExitCodeThread(hThrd,&exitCode);

                         if (!rc && exitCode != STILL_ACTIVE)

                                break;

                  }

    使用这个方法,必须持续不断的调用GetExitCodeThread(),直到其结果不再是STILL_ACTIVE书上说这方法不好,很浪费cpu时间.,称为忙等待(busy waits)忙等待必须应有的重视,不然你会发现当包含忙等待的程序运行起来后,其它正在进行的程序的反应就很迟钝了。因为cpu几乎用了所有的可用时间去检查线程是否结束。

     

    那么,我应该怎么做呢?如何才更有效率呢?

     

    另一种有效率的方法:

    使用WaitForSingleObject()这个函数来完美的解决问题。

    完成上面程序片段同样功能只需一句话:

    WaitForSingleObject ( hThrd, INFINITE );

    hThrd线程没有结束时,调用这个函数的程序就会在函数调用点停下来,直到hThrd线程结束时(术语:hThrd被激发)才继续向下执行。

    不知道大家会不会有这样疑问------这个函数不会只是把上面的程序片段包装了一下吧?它真是很有效率吗?如果它有效率,它是如何做到的呢?

    可以告诉大家,WaitForSingleObject()不是上述程序片段的简单包装,它真的很有效率(不信,按书上的方法,打开性能管理器看看),至于它如何做到的,我也有兴趣知道(知道告诉我),我只知道这个函数得到了操作系统级的某些底层调度函数的支持。

     

    基本上本章的核心内容就是以上所述了。(至于WaitForSingleObject()参数及返回值的说明,查书就行了,毋需多言)

     

     

    具体的看一个实在的例子,胜过在此长篇大论,下面请看:

    //参考书上例子

    //程序的目的:只用3个线程,完成6件事

    int main()

    {

                  HANDLE        hThrds[3];

     

                  int slot = 0;

                  For ( int I=1 ; I<=6 ; I++)

                  {

                         if( I > 3 )

                         {//已经存在3个线程了

    //等待其中的一个线程线束后,再创建线程做剩余的事情

    //效率不高,因为线程结束的次序与它们被产生的次序不同

    WaitForSingleObject( hThrds[slot] , INFINITE ) ;

    CloseHandle ( hThrds[slot] );

                         }

     

                         //构造线程

                         hThrds[slot] = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL);

                        

                         if (++slot>2)

                                slot=0;

    }// end for

     

    for ( slot=0; slot<3; slot++)

    {

           //等待剩余的线程结束

           WaitForSingleObject( hThrds[slot] , INFINITE ) ;

           CloseHandle ( hThrds[slot] );

    }// end for

    }

     

    上面的这段程序有一个问题,就是效率不是很高;理想的状况是,一旦有一个线程结束,就立刻产生一个线程补上。仔细读上面的程序,你会发现它无法实现理想的状况;因为它假设线程结束的次序会和它们被产生的次序相同。比如,当依序产生了1,2,3线程以后,一定是按1,2,3的次序结束。其实不然,也许21更早结束。在这时,上面的程序并不会立刻产生一个线程填补2,而是非要等1结束了,才产生线程。那么能够实现理想的状况吗?答案是可以,请用WaitForMultipleObjects() 函数, 这个函数的用法基本上与WaitForSingleObject()差不多,在这里我就不举例说明了。

     

    本章最后还提到了MsgWaitForMultipleObjects() , 这个函数特点是在消息到达或线程结束时返回。

     

    我想,只要用会了WaitForSingleObject()这个函数, 那么WaitForMultipleObjects()MsgWaitForMultipleObjects()看一下也就会用了(书上举了两个小例子来说明,看一下花不了多少时间,不必我在这里废话了)

     

    这一章节的内容大概就是这么多,总结一下:

    * 等待线程结束                  [  WaitForSingleObject()           ]

    * 等待多个线程结束              [  WaitForMultipleObjects()                ]

    * 等待多个线程结束或消息到达    [  MsgWaitForMultipleObjects()         ]

     

     

    附注:以上正文纯属加强记忆所做笔记,内容或有不详,甚至错误,请阅者见谅,匆见怪!!!

     


    最新回复(0)