线程等待WaitXXXXX()函数系列之WaitForSingleObject和WaitForMultipleObject

Wait*()函数族可以来实现事件的检测,改函数可以实现单信号和多信号的侦测。

可能我这么说大家可能会有点迷迷糊糊。不急,我们先来介绍两个函数。

第一个是用于单信号侦测。WaitForSingleObject()

函数原型

DWORD WaitForSingleObject(

HANDLE hHandle,

DWORD dwMilliseconds

);

hHandle对象句柄。可以指定一系列的对象,如EventJobMemory resourcenotificationMutexProcessSemaphoreThreadWaitable timer等。

dwMilliseconds定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMillisecondsINFINITE,对象被触发信号后,函数才会返回。

 

执行成功,返回值指示出引发函数返回的事件。它可能为以下值:

WAIT_ABANDONEDWAIT_OBJECT_0WAIT_TIMEOUTWAIT_FAILED

 

WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。

WAIT_ABANDONEDhHandlemutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值。

WAIT_OBJECT_0:核心对象已被激活

WAIT_TIMEOUT:等待超时

WAIT_FAILED:出现错误,可通过GetLastError得到错误代码

第二个是用于多信号侦测。WaitForMultipleObject()

函数原型

DWORD WaitForMultipleObject(

DWORD dwCount ,

CONST HANDLE* phObject,

 BOOL fWaitAll,

 DWORD dwMillisecinds

);

dwCount参数用于指明想要让函数查看的内核对象的数量。这个值必须在1MAXIMUM_WAIT_OBJECTS(Windows头文件中定义为64之间.

phObjects参数是指向内核对象句柄的数组指针。可以以两种不同的方式来使用WaitForMultipleObjects函数。一种方式是让线程进入等待状态,直到指定内核对象中的任何一个变为已通知状态。另一种方式是让线程进入等待状态,直到所有指定的内核对象都变为已通知状态。

fWaitAll参数告诉该函数,你想要让它使用何种方式。如果为该参数传递TRUE,那么在所有对象变为已通知状态之前,该函数将不允许调用线程运行。

dwMilliseconds参数该参数的作用与它在WaitForSingleObject中的作用完全相同。如果在等待的时候规定的时间到了,那么该函数无论如何都会返回。同样,通常为该参数传递INFINITE,但是在编写代码时应该小心,以避免出现死锁情况。

WaitForMultipleObjects函数的返回值告诉调用线程,为什么它会被重新调度。可能的返回值是WAIT_FAILEDWAIT_TIMEOUT,这两个值的作用是很清楚的。如果为f WaitAll参数传递TRUE,同时所有对象均变为已通知状态,那么返回值是WAIT_OBJECT_0。如果为fWaitAll传递FALSE,那么一旦任何一个对象变为已通知状态,该函数便返回。在这种情况下,你可能想要知道哪个对象变为已通知状态。返回值是WAIT_OBJECT_0与(WAIT_OBJECT_0 + dwCount-1)之间的一个值。换句话说,如果返回值不是WAIT_TIMEOUT,也不是WAIT_FAILED,那么应该从返回值中减去WAIT_OBJECT_0。产生的数字是作为第二个参数传递WaitForMultipleObjects的句柄数组中的索引。该索引说明哪个对象变为已通知状态。

 

两个函数的基本介绍看起来比较让人头疼,接下我们就用代码来帮助我们对其两个函数的理解。

多信号侦测

#include <windows.h>
#include <iostream>
using namespace std;
 
DWORD WINAPI Print_Thread(LPVOID data)
{
    cout<<"开始线程\n"<<(int)data+1;
for(int index=0;index<50*((int)data+1); index++)
//根据不同的循环次数来更加清楚的观察线程运行状况,
    {
       cout<<(int)data+1<<" ";
        Sleep(100);
    }
 
    cout<<"线程"<<(int)data+1<<"执行完毕\n";
    return (DWORD)data;
}
 
 
int main()
{
    HANDLE threadHandle[3];
    DWORD  threadID[3];
 
    for (int i=0;i<3;i++)
    {
       threadHandle[i]=CreateThread(
            NULL,
            0,
           Print_Thread,
            (LPVOID)i,
            0,
           &threadID[i]
            );
    }
  
 
    for (int index=0;index<25; index++)
    {
        cout<<"4"<<" ";
        Sleep(100);//等待100毫秒
    }
    cout<<"主线程结束,进入等待"<<endl;
   WaitForMultipleObjects(3,threadHandle,true,INFINITE);
 
    for(int i=0;i<3;i++)
     CloseHandle(threadHandle[i]);//关掉线程句柄
 
   
    return 0;
}


 

运行程序你会发现当主线程运行完后在等待子线程执行完直到结束

如果你将WaitForMultipleObjects(3,threadHandle,true,INFINITE);这句注释掉你就会发现主线程结束后直接就退出程序。而不会等待子线程。


如果你将WaitForMultipleObjects(3,threadHandle,true,INFINITE);里面的第三个参数改为false,则程序将会再任何一个子线程执行完后,程序就退出。而true是等待所有子线程结束。

 

这里只演示了多信号侦测,单信号而是同样的写法,很简单,大家可以去尝试一下。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。