提供一个“多线程(或进程)同时退出时判断是哪些线程退出”的方法

本文介绍了一种在Windows环境下利用WaitForMultipleObjects()函数监测多个线程退出状态的方法,并通过示例代码展示了如何准确获取已退出线程的信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在写多线程的时候,我们常常会有这样的苦恼:
1、WaitForMultipleObjects()这个函数在等待多个对象返回时,返回的总是最小的那个线程,但是我们很想知道到底是哪些线程退出了,可以依据退出的线程由主线程来针对地做一些处理。
2、WaitForMultipleObjects()等待的多个线程中,线程都处理不同的事务,并且运行的时间都不确定,有可能同时,有可能不同时,那我要怎么确定是哪个线程退出?

不多说其它东西,示例代码如下所示:

// MeloThreads.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>

//设定最大的运行数量
#define IMAX 10

//这个结构体可以用于描述线程的其他信息
typedef struct _myThread 
{
    int iTid;
    HANDLE hHandle;

    _myThread()
    {
        iTid = 0;
        hHandle = NULL;
    }
}MYTHREAD;

DWORD WINAPI ThreadWork(LPVOID lpParam);

int _tmain(int argc, _TCHAR* argv[])
{
    int i = 0;
    int iTotal = 0;
    MYTHREAD MyThread[IMAX];
    HANDLE nThread[IMAX];
    HANDLE hTmp;

    //在这里创建线程和进程都无所谓
    //不过在这里是线程
    for(i=0; i<IMAX; i++)
    {
        //有可能创建线程失败,失败就不记录数量
        if( hTmp = CreateThread(NULL, 0, ThreadWork, NULL, 0, NULL) )
        {
            nThread[iTotal] = hTmp;
            MyThread[iTotal].hHandle = hTmp;
            MyThread[iTotal].iTid = iTotal;
            iTotal++;
        }
    }

    //用于记录是那个对象是返回的
    int iIndex;
    //循环等待所有线程退出
    while (iTotal)
    {
        //等待线程退出
        //第一个参数:表示等待的线程数量,当有线程退出之后会减1
        //第二个参数:线程的句柄队列
        //第三个参数:表示只要有一个线程退出就返回
        //第四个参数:线程的超时时间
        iIndex = ::WaitForMultipleObjects(iTotal, nThread, false, INFINITE);
        iIndex = iIndex - WAIT_OBJECT_0;

        //只要不是返回-1(出错)
        if(-1 != iIndex)
        {
            //这里找出是哪个线程退出了,退出了则去掉这个进程的信息
            for(int i=0; i<IMAX; i++)
            {
                if ( MyThread[i].hHandle == nThread[iIndex] )
                {
                    printf("线程:%d 退出!\n", MyThread[i].iTid);
                    MyThread[i].iTid = 0;
                    MyThread[i].hHandle = NULL;
                    break;
                }
            }
            //这里如果不closehandle,那么等待的句柄队列就会包含一个无效句柄
            //那么函数WaitForMultipleObjects()就会返回-1
            CloseHandle(nThread[iIndex]);
            nThread[iIndex] = NULL;

            //关闭句柄之后将已经退出的句柄从队列中删掉,否则就会一直触发这个对象
            //然后将之后有效的句柄往前移,保证队列中所有的句柄都是有效的
            //最后等待的句柄数量减1
            for(int i=0; i<iTotal; i++)
            {
                if (i > iIndex)
                {
                    nThread[i-1] = nThread[i];
                }
            }
            nThread[--iTotal] = NULL; 
        }
    }
    return 0;
}

//线程的功能是数30秒后退出
DWORD WINAPI ThreadWork(LPVOID lpParam)
{
    for (int i=0; i<30; i++)
    {
        Sleep(1000);
    }
    return 0;
}

上述示例代码的结果:
这里写图片描述

由于提供的只是一种方法,所以示例代码比较精简,你可以使用用于其它应用场景。如有问题或者一些改进意见,麻烦请评论或者私信联系我,谢谢大家。

该示例的git地址:https://github.com/meloyi/MeloThreads/tree/master
示例的优快云下载地址:http://download.youkuaiyun.com/detail/meloyi/9677397

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值