在多线程下面,有时候会希望等待某一线程完成了再继续做其他事情,要实现这个目的,可以使用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. cameralink---格式 概要清晰理解

    DS90CR288 和DS90CR286共同组成LVDS收发对, LVDS: 4对数据+1对时钟 TTL: 时钟线1:clk 并行总线共27根: 同步线2:一根场同步,一根行同步 空闲: 1 数据线2 ...

  2. Ubuntu 14.04安装配置NFS服务器

    (一)安装NFS服务器1.1-安装Ubuntu nfs服务器端: sudo apt-get install nfs-kernel-server 1.2-安装nfs的客户端: sudo apt-get ...

  3. ubuntu 下root用户无法访问声音设备的解决方案

    原因:root用户没有对pulsaudio的访问权限,而且pulsaudio默认是不能在root下自动启动解决办法: 一.修改自动启动:编辑 gedit /etc/default/pulseaudio ...

  4. 在Eclipse新建菜单中添加JSP

    在开发的时候,大家可能选择不同的透视图,下面以Java EE透视图为例. 在项目上右键,选择new命令,出来的菜单中并没有新建JSP的选项. 这样一来,如果想新建JSP,只能选择Other命令,在里面 ...

  5. Matlab交集并集的实现

    >> a = [1 2 3 4 8 9]; >> b = [4 5 6 1] b = 4 5 6 1 >> c = intersect(a,b) c = 1 4 判 ...

  6. UIFontFamily

    Family: Hiragino Kaku Gothic ProN W3     Font: HiraKakuProN-W3 Family: Courier     Font: Courier     ...

  7. orbis 链接 .a的问题

    orbis-clang.exe :error: no such file or directory : libppfxd_delta.a 这个东西真是见鬼 明明在那里就是说找不到 在依赖里libppf ...

  8. mongo 1067错误

    对mongo进行错误的操作导致mongo服务异常关闭,当重启mongo服务时出现1067错误此时在data目录下产生mongod.lock文件,可以讲此文件删除,然后重启就可以了 Please mak ...

  9. Slim + Twig 构建PHP Web应用程序

    Twig : PHP 视图模板引擎,类似于Smart模板引擎. 下载地址:http://twig.sensiolabs.org/ Slim: 轻量级PHP MVC框架,可用于构建Web app,Res ...

  10. VS Bug 当获取其他项目的代码时, F5 无法进入调试模式. 也不报错....

    在64位的机子下, 被获用的项目使用X86时会出现. 就会出现   F5 无法进入调试模式. 也不报错.... 打断点也没有用. 在不加入X86项目的代码时, 又可以运行..   解决方案:   检查 ...