WaitForSingleObject

用户模式的线程同步机制效率高,如果需要考虑线程同步问题,应该首先考虑用户模式的线程同步方法。

  但是,用户模式的线程同步有限制,对于多个进程之间的线程同步,用户模式的线程同步方法无能为力。这时,只能考虑使用内核模式。

 

  Windows提供了许多内核对象来实现线程的同步。对于线程同步而言,这些内核对象有两个非常重要的状态:“已通知”状态,“未通知”状态(也有翻译为:受信状态,未受信状态)。Windows提供了几种内核对象可以处于已通知状态和未通知状态:进程、线程、作业、文件、控制台输入/输出/错误流、事件、等待定时器、信号量、互斥对象。

 

  你可以通知一个内核对象,使之处于“已通知状态”,然后让其他等待在该内核对象上的线程继续执行。你可以使用Windows提供的API函数,等待函数来等待某一个或某些内核对象变为已通知状态。

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

DWORD WaitForSingleObject(
   HANDLE hObject,     //指明一个内核对象的句柄
   DWORD dwMilliseconds);     //等待时间

 

  该函数需要传递一个内核对象句柄,该句柄标识一个内核对象,如果该内核对象处于未通知状态,则该函数导致线程进入阻塞状态;如果该内核对象处于已通知状态,则该函数立即返回WAIT_OBJECT_0。第二个参数指明了需要等待的时间(毫秒),可以传递INFINITE指明要无限期等待下去。如果等待超时,该函数返回WAIT_TIMEOUT。如果该函数失败,返回WAIT_FAILED。可以通过下面的代码来判断:

 

DWORD dw = WaitForSingleObject(hProcess, 5000); //等待一个进程结束
switch (dw)
{
   case WAIT_OBJECT_0:
      // hProcess所代表的进程在5秒内结束
       break;

   case WAIT_TIMEOUT:
      // 等待时间超过5秒
       break;

   case WAIT_FAILED:
      // 函数调用失败,比如传递了一个无效的句柄
       break;
}

 

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

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

 

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

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

  可以如下使用该函数:

 

HANDLE h[3];     //句柄数组

//三个进程句柄
h[0] = hProcess1;
h[1] = hProcess2;
h[2] = hProcess3;

DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); //等待3个进程结束

switch (dw)
{
   case WAIT_FAILED:
      // 函数呼叫失败
       break;

   case WAIT_TIMEOUT:
      // 超时
       break;

   case WAIT_OBJECT_0 + 0:
      // h[0](hProcess1)所代表的进程结束
       break;

   case WAIT_OBJECT_0 + 1:
      // h[1](hProcess2)所代表的进程结束
       break;

   case WAIT_OBJECT_0 + 2:
      // h[2](hProcess3)所代表的进程结束
       break;
}

 

  你也可以同时通知一个内核对象,同时等待另一个内核对象,这两个操作以原子的方式进行:

DWORD SignalObjectAndWait(
   HANDLE hObjectToSignal,   //通知的内核对象
   HANDLE hObjectToWaitOn,   //等待的内核对象
   DWORD dwMilliseconds,     //等待的时间
   BOOL bAlertable);         //与IO完成端口有关的参数,暂不讨论

 

  该函数在内部使得hObjectToSignal参数所指明的内核对象变成已通知状态,同时等待hObjectToWaitOn参数所代表的内核对象。dwMilliseconds参数的用法与WaitForSingleObject函数类似。
  该函数返回如下:WAIT_OBJECT_0,WAIT_TIMEOUT,WAIT_FAILED,WAIT_IO_COMPLETION。

  等你需要通知一个互斥内核对象并等待一个事件内核对象的时候,可以这么写:

ReleaseMutex(hMutex);
WaitForSingleObject(hEvent, INFINITE);

  可是,这样的代码不是以原子的方式来操纵这两个内核对象。因此,可以更改如下:

SignalObjectAndWait(hMutex, hEvent, INFINITE, FALSE);

时间: 2024-11-02 00:54:11

WaitForSingleObject的相关文章

WaitForSingleObject函数

WaitForSingleObject函数 VC声明 DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ); VB声明 Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long 编辑本段说明 DWORD WINAPI WaitForSingl

核心编程随笔3

Note 1:一个线程可以调用以下两个函数来获取和设置其进程的当前驱动器和目录:DWORD GetCurrentDirectory(DWORD cchCurDir,PTSTR pszCurDir);BOOL SetCurrentDirectory(PCTSTR pszCurDir);注意WinDef.h文件中被定义为260的常量MAX_PATH是目录名称或文件名称的最大字符数.所以在调用GetCurrentDirectory的时候,向该函数传递由MAX_PATH个TCHAR类型的元素构成的一个缓

线程-操作系统,进程同步实验的问题

问题描述 操作系统,进程同步实验的问题 操作系统 进程同步 实验中 我们模拟了这一个小小的程序,如下: #include <stdio.h>#include <stdlib.h>#include <windows.h>int c1 = 0;int c2 = 0;int will_wait;int accnt1 = 0;int accnt2 = 0;DWORD WINAPI run1( LPVOID p ) { unsigned long counter = 0; int

vc++-信号量和线程同步的问题:线程函数比较耗时

问题描述 信号量和线程同步的问题:线程函数比较耗时 void trigger() { UINT uWait=::WaitForSingleObject(IEvent,INFINITE); if ( uWait == WAIT_OBJECT_0 ) { processA(); } } processA(); 比较耗时,如果它还没有跑完,下一个触发又来了,就马上又开始执行一个processA(); 吗,还是等待上次的执行完成然后再执行? 解决方案 PC机上会出现乱序或是假死,也就是说有可能后发的先做

ACE框架reactor同步问题求助?

问题描述 ACE框架reactor同步问题求助? //小弟在ACE reactor框架中开启一个定时器和一个接受器,代码如下:class Timer: public ACE_Event_Handler { virtual int handle_timeout (const ACE_Time_Value &current_timeconst void *act = 0);} int ACE_TMAIN(int argcACE_TCHAR *argv[]){ Sgl_Timer::instance(

Detours 拦截API导致目标程序崩溃

问题描述 Detours 拦截API导致目标程序崩溃 系统环境为Windows7,X64,注入程序,DLL,目标程序为VS2013生成的Win32项目 代码再回复中贴出 解决方案 数组越界导致程序崩溃 解决方案二: // dllmain.cpp : Defines the entry point for the DLL application. #include "stdafx.h" #include "detours.h" #include #include #i

用C++解决理发师问题

#include<cstdarg> #include<Windows.h> #include<iostream> #include <cmath> #include<ctime> #define MAX_COUNT 10//最多理发人数 #define CHAIRS 4//店中椅子的总数目 using namespace std; intwaiting=0;          //等待理发的顾客人数 char    close_door;    

asp调用vb生成的dll文件,执行shell异步变同步的解决方法(带源代码)

vb|解决|源代码|执行|shell|异步|同步 阿里西西web开发团队在开发一个asp系统,需要同步调用vb(dll)执行的shell操作,asp->vb(dll)->shell->rar.exe同步执行exe文件. 由于shell是异步处理,这个问题让我们头疼了很久,最终还是通过百度找到了几个不错的函数,调试过,效果还不错,建议可以先用vb建exe来调试好了,再放入DLL编译给ASP调用. 代码如下: 以下是用vb制作一个exe文件进行调试,打开记事本和计算器示例:Private T

让Java程序自带JRE

程序   用Java开发程序,发布时总要考虑的问题就是怎么在使用者的机器上装好JRE.要考虑的问题很多:使用者有没有能力独自安装JRE,使用者已有的JRE和我们需要的版本是不是一致,会不会出现版本问题,等等.使用.NET要考虑的问题就少些.现在.NET CLR似乎已经很普及了,看好多D版的Win XP都会自己安装最新的.NET CLR,而且似乎它的安装界面也比JRE友好些.彻底解决安装JRE的问题的方案,就是让我们的应用程序自己背着JRE!这样,我们的程序就像传统的Win32应用程序一样,双击就