线程等待WaitXXXXX()函数系列之WaitForSingleObject和WaitForMultipleObject
Wait*()函数族可以来实现事件的检测,改函数可以实现单信号和多信号的侦测。
可能我这么说大家可能会有点迷迷糊糊。不急,我们先来介绍两个函数。
第一个是用于单信号侦测。WaitForSingleObject()
函数原型
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
hHandle对象句柄。可以指定一系列的对象,如Event、Job、Memory resourcenotification、Mutex、Process、Semaphore、Thread、Waitable timer等。
dwMilliseconds定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。
执行成功,返回值指示出引发函数返回的事件。它可能为以下值:
WAIT_ABANDONED,WAIT_OBJECT_0,WAIT_TIMEOUT,WAIT_FAILED。
WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。
WAIT_ABANDONED:当hHandle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值。
WAIT_OBJECT_0:核心对象已被激活
WAIT_TIMEOUT:等待超时
WAIT_FAILED:出现错误,可通过GetLastError得到错误代码
第二个是用于多信号侦测。WaitForMultipleObject()
函数原型
DWORD WaitForMultipleObject(
DWORD dwCount ,
CONST HANDLE* phObject,
BOOL fWaitAll,
DWORD dwMillisecinds
);
dwCount参数用于指明想要让函数查看的内核对象的数量。这个值必须在1与MAXIMUM_WAIT_OBJECTS(在Windows头文件中定义为64之间.
phObjects参数是指向内核对象句柄的数组的指针。可以以两种不同的方式来使用WaitForMultipleObjects函数。一种方式是让线程进入等待状态,直到指定内核对象中的任何一个变为已通知状态。另一种方式是让线程进入等待状态,直到所有指定的内核对象都变为已通知状态。
fWaitAll参数告诉该函数,你想要让它使用何种方式。如果为该参数传递TRUE,那么在所有对象变为已通知状态之前,该函数将不允许调用线程运行。
dwMilliseconds参数该参数的作用与它在WaitForSingleObject中的作用完全相同。如果在等待的时候规定的时间到了,那么该函数无论如何都会返回。同样,通常为该参数传递INFINITE,但是在编写代码时应该小心,以避免出现死锁情况。
WaitForMultipleObjects函数的返回值告诉调用线程,为什么它会被重新调度。可能的返回值是WAIT_FAILED和WAIT_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是等待所有子线程结束。
这里只演示了多信号侦测,单信号而是同样的写法,很简单,大家可以去尝试一下。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。