在多线程下面,有时候会希望等待某一线程完成了再继续做其他事情,要实现这个目的,可以使用Windows API函数WaitForSingleObject,或者WaitForMultipleObjects。这两个函数都会等待Object被标为有信号(signaled)时才返回的。
那么,什么是信号呢?简单来说,Windows下创建的Object都会被赋予一个状态量。如果Object被激活了,或者正在使用,那么该Object就是无信号,也就是不可用;另一方面,如果Object可用了,那么它就恢复有信号了。这两个函数的优点是它们在等待的过程中会进入一个非常高效沉睡状态,只占用极少的CPU时间片。(这两个函数都是在内核状态下等待内核对象,不切换到用户模式下,因而效率很高)

WaitForSingleObject函数来等待一个内核对象变为已通知状态:

DWORD WaitForSingleObject(

HANDLE hObject, //指明一个内核对象的句柄

DWORD dwMilliseconds); //等待时间

该函数需要传递一个内核对象句柄,该句柄标识一个内核对象,

如果该内核对象处于未通知状态,则该函数导致线程进入阻塞状态;

如果该内核对象处于已通知状态,则该函数立即返回WAIT_OBJECT_0。

第二个参数指明了需要等待的时间(毫秒),可以传递INFINITE指明要无限期等待下去,

如果第二个参数为0,那么函数就测试同步对象的状态并立即返回。

如果等待超时,该函数返回WAIT_TIMEOUT。

如果该函数失败,返回WAIT_FAILED。可以通过下面的代码来判断

  1. LPVOID lpMsgBuf;
  2. FormatMessage(
  3. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  4. FORMAT_MESSAGE_FROM_SYSTEM |
  5. FORMAT_MESSAGE_IGNORE_INSERTS,
  6. NULL,
  7. GetLastError(),
  8. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  9. (LPTSTR) &lpMsgBuf,
  10. 0,
  11. NULL
  12. );
  13. MessageBox(  (LPCTSTR)lpMsgBuf);
  14. LocalFree( lpMsgBuf );

--------------------------------------------WaitForMultipleObjects()-------------------------------------------

  1. <span style="font-size:18px;">WaitForMultipleObjects()允许你在同一时间等待一个以上的对象。
  2. DWORD WaitForMultipleObject(
  3. DWORD  nCount,   //表示lphandles数组的元素个数
  4. CONST HANDLE  *lphandles,  //指向一个有对象handles组成的数组。
  5. BOOL  bWaitAll,            //如果为true,则表示所有的handles都必须激发,此函数才得以返回,否则,此函数将在任何一个handle激发时就返回。
  6. DWORD dwMilliseconds    //超时也返回,可为0,立即返回,INFINITE表示无穷等待。
  7. );</span>

返回值:
如果因时间终了而返回,则返回值是WAIT_TIMEOUT,类似WaitForSingleObject().
如果bWaitAll是TRUE,则返回值将是WAIT_OBJECT_0.
如果bWaitAll是FALSE,那么将返回值减去WAIT_OBJECT_0,就表示数组中的哪一个handle被激发了。
如果你等待的对象中有任何mutexes,那么返回值可能从WAIT_ABANDONED_0到WAIT_ABANDONED_0+nCount-1.
如果函数失败,则返回WAIT_FAILED。可以使用GetLastError找出失败原因。

WaitForSingleObject测试方法:

  1. DWORD dw = WaitForSingleObject(hProcess, 5000); //等待一个进程结束
  2. switch (dw)
  3. {
  4. case WAIT_OBJECT_0:
  5. // hProcess所代表的进程在5秒内结束
  6. break;
  7. case WAIT_TIMEOUT:
  8. // 等待时间超过5秒
  9. break;
  10. case WAIT_FAILED:
  11. // 函数调用失败,比如传递了一个无效的句柄
  12. break;
  13. }

WaitForSingleObject测试方法:

WaitForMulitpleObjects函数来等待多个内核对象变为已通知状态:

  1. DWORD WaitForMultipleObjects(
  2. DWORD dwCount, //等待的内核对象个数
  3. CONST HANDLE* phObjects, //一个存放被等待的内核对象句柄的数组
  4. BOOL bWaitAll, //是否等到所有内核对象为已通知状态后才返回
  5. DWORD dwMilliseconds); //等待时间

该函数的第一个参数指明等待的内核对象的个数,可以是0到MAXIMUM_WAIT_OBJECTS(64)中的一个值。phObjects参数是一个存放等待的内核对象句柄的数组。bWaitAll参数如果为TRUE,则只有当等待的所有内核对象为已通知状态时函数才返回,如果为FALSE,则只要一个内核对象为已通知状态,则该函数返回。第四个参数和WaitForSingleObject中的dwMilliseconds参数类似。

该函数失败,返回WAIT_FAILED;如果超时,返回WAIT_TIMEOUT;如果bWaitAll参数为TRUE,函数成功则返回WAIT_OBJECT_0,如果bWaitAll为FALSE,函数成功则返回值指明是哪个内核对象收到通知。

可以如下使用该函数:

  1. HANDLE h[3]; //句柄数组
  2. //三个进程句柄
  3. h[0] = hProcess1;
  4. h[1] = hProcess2;
  5. h[2] = hProcess3;
  6. DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); //等待3个进程结束
  7. switch (dw)
  8. {
  9. case WAIT_FAILED:
  10. // 函数呼叫失败
  11. break;
  12. case WAIT_TIMEOUT:
  13. // 超时
  14. break;
  15. case WAIT_OBJECT_0 + 0:
  16. // h[0](hProcess1)所代表的进程结束
  17. break;
  18. case WAIT_OBJECT_0 + 1:
  19. // h[1](hProcess2)所代表的进程结束
  20. break;
  21. case WAIT_OBJECT_0 + 2:
  22. // h[2](hProcess3)所代表的进程结束
  23. break;
  24. }

附:测试代码下载地址 :http://download.csdn.net/detail/makenothing/9497235

http://blog.csdn.net/makenothing/article/details/51197726

WaitForSingleObject与WaitForMultipleObjects用法详解(好用,而且进入一个非常高效沉睡状态,只占用极少的CPU时间片)的更多相关文章

  1. WaitForMultipleObjects用法详解

    本文转载于:http://blog.csdn.net/sac761/article/details/52456385 WaitForMultipleObjects是Windows中的一个功能非常强大的 ...

  2. Ext.Net学习笔记22:Ext.Net Tree 用法详解

    Ext.Net学习笔记22:Ext.Net Tree 用法详解 上面的图片是一个简单的树,使用Ext.Net来创建这样的树结构非常简单,代码如下: <ext:TreePanel runat=&q ...

  3. C++中的STL中map用法详解(转)

    原文地址: https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html C++中的STL中map用法详解   Map是STL的一个关联容器,它提供 ...

  4. C#中string.format用法详解

    C#中string.format用法详解 本文实例总结了C#中string.format用法.分享给大家供大家参考.具体分析如下: String.Format 方法的几种定义: String.Form ...

  5. @RequestMapping 用法详解之地址映射

    @RequestMapping 用法详解之地址映射 引言: 前段时间项目中用到了RESTful模式来开发程序,但是当用POST.PUT模式提交数据时,发现服务器端接受不到提交的数据(服务器端参数绑定没 ...

  6. linux管道命令grep命令参数及用法详解---附使用案例|grep

    功能说明:查找文件里符合条件的字符串. 语 法:grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>] ...

  7. mysql中event的用法详解

    一.基本概念mysql5.1版本开始引进event概念.event既“时间触发器”,与triggers的事件触发不同,event类似与linux crontab计划任务,用于时间触发.通过单独或调用存 ...

  8. CSS中伪类及伪元素用法详解

    CSS中伪类及伪元素用法详解   伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的 ...

  9. c++中vector的用法详解

    c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间 ...

随机推荐

  1. 二、IRIG_B解码AC信号

    AC-----过零检测(MAX913ESA)---1khzB码信号(以0v为界大于0为高,小于0为低,的 方波信号) AC-----信号放大(TLE2022ID--mv到5v) ---系统电压转换(M ...

  2. 【BOZJ 1901】Zju2112 Dynamic Rankings

    Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是 ...

  3. USB硬件远程共享解决iphone已停用

    悲剧的在iphone拆过电池之后,再开机显示iphone已停用,请在23000000分钟后再试一次 算算这得45年了,可以留给孙子用了... 网上除了刷机和有同步过的电脑貌似没有别的办法了 因是旧系统 ...

  4. Android -- 经验分享

    目录                                                                                             代码中安装 ...

  5. IDEA for Mac 解决控制台乱码问题

    近期发现 idea for mac 版本中 tomcat 控制台有中文的地方出现乱码问题,其实很简单就可以解决. 这里做个笔记,以后可以方便不会的人来解决 ---------------------- ...

  6. [百度空间] [原]android下的各种坑

    一堆so文件安装不正确: apk里面都是全的, 但是安装完后/data/data/$pkg/lib下面就没有 google了好长时间没有结果.最后发现是因为没库有加lib前缀(当时想了一下觉得不加更好 ...

  7. WinHex分析PE格式(2)&& 如何手动添加区段并运行区段

    由于这次文章内容比较多 所以写成DOC文档 为了复习所学的知识,我在原本的软件里试者手动加入区段 ,并写给大家分享,还试试者用LordPE加区段发现竟然失败了, 还是自己动手比较实在,完美运行. 利用 ...

  8. openSSL漏洞原理及安全加固

    2014年4月8日晚,互联网爆出了又一重量级安全漏洞,即CVE-2014-0160,通俗来讲就是OpenSSL出现了安全漏洞. 说 这个漏洞前,先介绍一下OpenSSL,OpenSSL是一个强大的安全 ...

  9. IE8下兼容rgba颜色的半透明背景

    在工作中做一个图片半透明遮罩时发现在IE8下不兼容 一查再知道IE8不支持rgba颜色,再搜搜兼容性方法,没想到这么快就解决了. 先说说rgba的含义: r代表red,g代表green,b代表blue ...

  10. Javascript 性能优化的一点技巧

    把优秀的编程方式当成一种习惯,融入到日常的编程当中.下图是今天想到的一点Javascript 性能优化的技巧,分享一下,抛砖引玉.