线程等待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是等待所有子线程结束。

 

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

时间: 2024-10-21 11:55:19

线程等待WaitXXXXX()函数系列之WaitForSingleObject和WaitForMultipleObject的相关文章

posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序

posix 线程(一):线程模型.pthread 系列函数 和 简单多线程服务器端程序 一.线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属于1:1模型. (一).N:1用户线程模型 “线程实现”建立在“进程控制”机制之上,由用户空间的程序库来管理.OS内核完全不知道线程信息.这些线程称为用户空间线程.这些线程都工作在“进 程竞争范围”(process contention scope):各个线程在同一进程竞争“被调度的CPU时间”(但

对线程等待函数pthread_join二级指针参数分析

分析之前先搞明白,这个二级指针其实在函数内部是承接了上个线程的返回值. 看man手册,发现返回值是个普通指针.人家用二级指针来承接,可能准备干大事.这个可以自己搜索一下.原因嘛,二级指针是保存了这个地址.一级指针承接的话就是这个地址. 那既然二级指针保存了,我们如何访问那?开始我觉得直接来个二级指针,然后*访问算了,但是下面的东西.让你不能那么干了!其实非要那样也可以 malloc呗! 线程创建函数pthread_create的函数原型如下: int pthread_create(pthread

Java多线程系列---“基础篇”05之 线程等待与唤醒

转自:https://www.cnblogs.com/skywang12345/p/3479224.html  (含部分修改) 概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括: wait(), notify(), notifyAll()等方法介绍 wait()和notify() wait(long timeout)和notify() wait() 和 notifyAll() 为什么notify(), wait()等函数定义在Object中,而不是Thread中 一. wait(),

线程等内核函数

from:http://blog.csdn.net/eric_arrow/article/details/19411067 m_hTheard = CreateThread(NULL,0,RegNotifyProc,LPVOID(this),0,NULL); CloseHandle(m_hTheard); 突然给糊涂了,刚创建的线程,为什么有close了,还是当初入门不踏实,没有细想,现在反过来都记不得了,通过查资料,解决了我的疑惑. 1,线程和线程句柄(Handle)不同,线程是一个程序的工作

线程中CreateEvent和SetEvent及WaitForSingleObject的用法

线程中CreateEvent和SetEvent及WaitForSingleObject的用法 首先介绍CreateEvent是创建windows事件的意思,作用主要用在判断线程退出,程锁定方面. CreateEvent 函功能描述:创建或打开一个命名的或无名的事件对象. EVENT有两种状态:发信号,不发信号. SetEvent/ResetEvent分别将EVENT置为这两种状态分别是发信号与不发信号. WaitForSingleObject()等待,直到参数所指定的OBJECT成为发信号状态时

Win32线程安全问题.同步函数

线程安全问题.同步函数 一丶简介什么是线程安全 通过上面几讲.我们知道了线程怎么创建.线程切换的原理(CONTEXT结构) 每个线程在切换的时候都有自己的堆栈. 但是这样会有安全问题. 为什么?  我们每个线程都使用自己的局部变量这个是没有安全问题的. 但是线程可能会使用全局变量.这样很有可能会产生安全问题.为什么是很有可能. 1.有全局变量的情况下.有可能会有安全问题. 2.对全局变量进行写操作.则一定有安全问题. 上面两个条件都具备,线程才是不安全的. 为什么是不安全的. 试想一下. 如果这

【函数】Oracle函数系列(1)--字符函数

[函数]Oracle函数系列(1)--字符函数 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 常见字符函数(lower.upper.initcap.concat.substr.length.intr.lpad.rpad.trim.chr.ascii.replace.translate)的使用 ② 判断字符串中是否含有汉字 ③ substr和instr的联合使用 ④

线程等待——CountDownLatch使用

告警性能优化过程中,遇到如下问题:1. 在数据库计算几十万个实体的KPI值的方差:2. 计算结果进行表格化处理. 这里KPI包含多个Counter的数据库函数运算(比如Decode,AVG等函数),方差也是数据库函数运算,性能比较差. 步骤1中每个实体独立计算方差,步骤2需要方差结果协同处理,所以很自然的联想到步骤1分实体多线程处理,步骤2等待步骤1所有线程完成后才开始处理.这里我们使用CountDownLatch进行线程等待,示例代码如下: package com.coshaho.thread

Linux多线程(二)(线程等待,退出)

1. 线程的等待退出 1.1. 等待线程退出 线程从入口点函数自然返回,或者主动调用pthread_exit()函数,都可以让线程正常终止 线程从入口点函数自然返回时,函数返回值可以被其它线程用pthread_join函数获取 pthread_join原型为: #include <pthread.h> int pthread_join(pthread_t th, void **thread_return); 1. 该函数是一个阻塞函数,一直等到参数th指定的线程返回:与多进程中的wait或wa