zoukankan      html  css  js  c++  java
  • windows多线程(二) 等待线程返回

    多线程编程中,有时我们需要等待某一线程完成了特定的操作后再继续做其他事情,要实现这个目的,可以使用Windows API函数WaitForSingleObject,或者WaitForMultipleObjects。这两个函数都会等待Object被标为有信号(signaled)时才返回。只要是Windows创建的Object都会被赋予一个状态量。如果Object被激活了,或者正在使用,那么该Object就是无信号,也就是不可用;另一方面,如果Object可用了,那么它就恢复有信号了。

    一、 等待单个线程返回 WaitForSingleObject

    1. 函数原型

    
    DWORD WINAPI WaitForSingleObject(
        _In_ HANDLE hHandle,
        _In_ DWORD dwMilliseconds
        );
    
    

    2.参数说明

    第一个参数 _In_ HANDLE hHandle 是对象的句柄,可以是以下几种:

    • Change notification
    • Console input
    • Event
    • Memory resource notification
    • Mutex
    • Process
    • Semaphore
    • Thread
    • Waitable timer

    第二个参数 _In_ DWORD dwMilliseconds 为等待时间,以毫秒为单位。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。

    3.返回值

    • WAIT_ABANDONED 0x00000080:当hHandle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值。
    • WAIT_OBJECT_0 0x00000000 :指定的对象出有有信号状态
    • WAIT_TIMEOUT 0x00000102:等待超时
    • WAIT_FAILED 0xFFFFFFFF :出现错误,可通过GetLastError得到错误代码

    4.实例

    1.参数 dwMilliseconds 为0,则该函数立即返回

    
    	
    #include <stdio.h>
    #include <windows.h>
    
    DWORD WINAPI  ThreadFunc(LPVOID);
    
    int main()
    {
    	HANDLE hThread;
    
    	hThread = CreateThread(NULL, 0, ThreadFunc, 0, 0, NULL); // 创建线程
    	printf("我是主线程, pid = %d
    ", GetCurrentThreadId());  //输出主线程pid
    	
    	WaitForSingleObject(hThread,0);	//不等待,直接返回
    	return 0;
    }
    
    DWORD WINAPI  ThreadFunc(LPVOID p)
    {
    	Sleep(10000); //睡眠10秒
    	printf("我是子线程, pid = %d
    ", GetCurrentThreadId());   //输出子线程pid
    	
    	return 0;
    }
    
    

    输出如下图,主线程不等待子线程返回,直接返回。

    2.参数 dwMilliseconds 为5000,等待5秒后返回。

    
    
    #include <stdio.h>
    #include <windows.h>
    
    DWORD WINAPI  ThreadFunc(LPVOID);
    
    int main()
    {
    	HANDLE hThread;
    
    	hThread = CreateThread(NULL, 0, ThreadFunc, 0, 0, NULL); // 创建线程
    	printf("我是主线程, pid = %d
    ", GetCurrentThreadId());  //输出主线程pid
    	
    	WaitForSingleObject(hThread,5000);	//等待5s
    	return 0;
    }
    
    DWORD WINAPI  ThreadFunc(LPVOID p)
    {
    	printf("我是, pid = %d 的子线程
    ", GetCurrentThreadId());   //输出子线程pid
    	Sleep(10000); //睡眠10秒
    	printf(" pid = %d 的子线程退出
    ", GetCurrentThreadId());    //延时10s后输出
    	
    	return 0;
    }
    
    

    输出如下图,主线程等待子线程5秒后,子线程还没有执行完,WaitForSingleObject就返回了。

    3.参数 dwMilliseconds 为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止

    
    #include <stdio.h>
    #include <windows.h>
    
    DWORD WINAPI  ThreadFunc(LPVOID);
    
    int main()
    {
    	HANDLE hThread;
    
    	hThread = CreateThread(NULL, 0, ThreadFunc, 0, 0, NULL); // 创建线程
    	printf("我是主线程, pid = %d
    ", GetCurrentThreadId());  //输出主线程pid
    	
    	WaitForSingleObject(hThread,INFINITE);	//一直等待,直到子线程返回
    	return 0;
    }
    
    DWORD WINAPI  ThreadFunc(LPVOID p)
    {
    	printf("我是, pid = %d 的子线程
    ", GetCurrentThreadId());   //输出子线程pid
    	Sleep(10000); //睡眠10秒
    	printf(" pid = %d 的子线程退出
    ", GetCurrentThreadId());   //延时10s后输出
    	
    	return 0;
    }
    
    

    输出如下图,主线程一直等待直到子线程还没有执行完毕。

    二、 等待多个线程返回 WaitForMulitpleObjects

    1. 函数原型

    DWORD WINAPI WaitForMultipleObjects(
      _In_       DWORD   nCount,
      _In_ const HANDLE  *lpHandles,
      _In_       BOOL    bWaitAll,
      _In_       DWORD   dwMilliseconds
    );
    
    

    2.参数说明

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

    3.实例

    1.参数 bWaitAll 为 false,只要一个内核对象为已通知状态,则该函数返回。

    
    #include <stdio.h>
    #include <windows.h>
    
    const unsigned int THREAD_NUM = 10;
    DWORD WINAPI  ThreadFunc(LPVOID);
    
    int main()
    {
    	printf("我是主线程, pid = %d
    ", GetCurrentThreadId());  //输出主线程pid
    	HANDLE hThread[THREAD_NUM];
    	for (int i = 0; i < THREAD_NUM; i++)
    	{
    		hThread[i] = CreateThread(NULL, 0, ThreadFunc, &i, 0, NULL); // 创建线程
    	}
    	
    	WaitForMultipleObjects(THREAD_NUM,hThread,false, INFINITE);	//只要有一个线程返回就结束
    	return 0;
    }
    
    DWORD WINAPI  ThreadFunc(LPVOID p)
    {
    	int n = *(int*)p;
    	Sleep(1000*n); //第 n 个线程睡眠 n 秒
    	printf("我是, pid = %d 的子线程
    ", GetCurrentThreadId());   //输出子线程pid
    	printf(" pid = %d 的子线程退出
    ", GetCurrentThreadId());   
    
    	return 0;
    }
    
    

    输出如下图,只要有一个线程返回就不再等待其它线程。

    2.参数 bWaitAll 为 true,等待所有线程返回。

    
    
    #include <stdio.h>
    #include <windows.h>
    
    const unsigned int THREAD_NUM = 10;
    DWORD WINAPI  ThreadFunc(LPVOID);
    
    int main()
    {
    	printf("我是主线程, pid = %d
    ", GetCurrentThreadId());  //输出主线程pid
    	HANDLE hThread[THREAD_NUM];
    	for (int i = 0; i < THREAD_NUM; i++)
    	{
    		hThread[i] = CreateThread(NULL, 0, ThreadFunc, &i, 0, NULL); // 创建线程
    	}
    	
    	WaitForMultipleObjects(THREAD_NUM,hThread,true, INFINITE);	//一直等待,直到所有子线程全部返回
    	return 0;
    }
    
    DWORD WINAPI  ThreadFunc(LPVOID p)
    {
    	int n = *(int*)p;
    	Sleep(1000*n);  //第 n 个线程睡眠 n 秒
    	printf("我是, pid = %d 的子线程	", GetCurrentThreadId());   //输出子线程pid
    	printf(" pid = %d 的子线程退出
    
    ", GetCurrentThreadId());   //延时10s后输出
    
    	return 0;
    }
    
    

    输出如下图,主线程等待所有线程返回。

    好了,关于WaitForSingleObject 和 WaitForMultipleObjects这两个函数的介绍就先到这里。 另外上面图中有一行显示了三列,这是正常现象,是由于没有做线程同步造成的,关于线程同步的知识,将在以后的文章中介绍。毕竟多线程的精髓就是线程同步问题。

  • 相关阅读:
    json.stringify()和json.parse()
    C# 对json对象嵌套数组
    sql 时间段内没有的数据等于0
    epoint:TreeView
    Asp.Net使用org.in2bits.MyXls.dll操作excel的应用
    VS中的生成事件
    mysql主从复制
    mysql索引优化分析
    MySQL逻辑架构简介
    大数据DMP画像系统(转载 简介-龙果学院)
  • 原文地址:https://www.cnblogs.com/ay-a/p/8763274.html
Copyright © 2011-2022 走看看