C++ 使用 WaitForMultipleObjects 检测哪个线程完成

C++ detecting which thread is done using WaitForMultipleObjects

我正在尝试同时 运行 3 个线程,然后在主线程中检测哪个线程已完成。我正在使用 WaitForMultipleObject 函数,但第 3 个线程似乎为此 WFMO 函数循环,而它已经完成了它的工作(打印结果)。

    #include <Windows.h>
    #include <stdio.h>
    #include <conio.h>
    //---------------------------------------------------------------------------
    #pragma argsused
    struct data 
    {
        char name[50];
    } data[3] = { { "[THREAD 0]" }, { "[THREAD 1]" },{ "[THREAD 2]" } };

    DWORD WINAPI th0()
{
    //here are some calculations
    //also added 1s sleep

    //printing result
    return 0;

}
DWORD WINAPI th1()
{
    //here are some other calculations
    //also added 1s sleep

    //printing result

    return 0;
}
DWORD WINAPI th2()
{
    //here are some other simple calculations
    //also added 1s sleep


    //printing result
    return 0;
}


    int priority[3] = { 0,0, 0};
    HANDLE threads[3]; 
    HANDLE functions[3];


    int main(int argc, char **argv)
    {
        int i;
        DWORD id; // thread's id

        printf("Program started...\n");

        functions[0] = th0;
        functions[1] = th1;
        functions[2] = th2; 
        for (i = 0; i < 3; i++)
        {
            threads[i] = CreateThread(
                NULL, // security atributes
                0, // stack size
                (LPTHREAD_START_ROUTINE)functions[i], // threads
                NULL,// input data for threads
                0, // creation's flags
                &id);//thread's id
            if (threads[i] != INVALID_HANDLE_VALUE)
            {
                printf("Created thread %s with ID: %x\n",
                    data[i].name, id);          
                SetThreadPriority(threads[i], priority[i]);
            }
        }
        bool f0=false, f1=false, f2=false;
        while(!f0 || !f1 || !f2)//while there is any unfinished thread
        {
            DWORD wfmo = WaitForMultipleObjects(3, threads, false, INFINITE);

            if (!f0 && WAIT_OBJECT_0==wfmo)
            {
                printf("%s is done!\n", data[0].name);
                f0=true;
                //CloseHandle(threads[0]);
                //threads[0]=NULL;

            }
            if (!f1 && WAIT_OBJECT_0 +1 == wfmo)
            {
                printf("%s is done!\n", data[1].name);
                f1=true;
                //CloseHandle(watki[1]);
                //watki[1]=NULL;

            }
            if (!f2 && WAIT_OBJECT_0 +2 == wfmo)
            {
                printf("%s is done!\n", data[2].name);
                f2=true;
                //CloseHandle(threads[2]);
                //threads[2]=NULL;
            }
            if(wfmo==WAIT_TIMEOUT)
                printf("timeout\n");
            if(wfmo==WAIT_FAILED)
                printf("failed\n");
        }


        //Sleep(20000); //20s
        return 0;
    }

输出:

    Program started... 
    Created thread [THREAD 0] with ID: b00 
    Created thread [THREAD 1] with ID: a64 
    Created thread [THREAD 2] with ID: 7d0 
    [THREAD 2] Result: 131072 
    [THREAD 1] Result: 121393 
    [THREAD 0] Result: 362880 
    [THREAD 2] is done! 
    [THREAD 0] is done!

来自 MSDN WaitForMultipleObjects 文档:

If bWaitAll is FALSE, the return value minus WAIT_OBJECT_0 indicates the lpHandles array index of the object that satisfied the wait. If more than one object became signaled during the call, this is the array index of the signaled object with the smallest index value of all the signaled objects.

线程 0 完成后,return 值将始终为 WAIT_OBJECT_0

解决方案(而不是 while 循环):

DWORD wfmo = WaitForMultipleObjects(3, threads, false, INFINITE);
//HANDLE threads2[2];   
if ( WAIT_OBJECT_0==wfmo)//move th1 and th2 up 
{
    printf("%s is done!\n", data[0].name);
    threads[0]=threads[1];
    threads[1]=threads[2];
    data[0]=data[1];
    data[1]=data[2];
    threads[2]=NULL;

}
else if ( WAIT_OBJECT_0 +1 == wfmo) //move th2 up
{
    printf("%s is done!\n", data[1].name);      
    threads[1]=threads[2];
    data[1]=data[2];
    threads[2]=NULL;
}
else if (  WAIT_OBJECT_0 +2 == wfmo)//no need to do anything
{
    printf("%s is done!\n", data[2].name);
    threads[2]=NULL;
}

wfmo = WaitForMultipleObjects(2, threads, false, INFINITE); 
if ( WAIT_OBJECT_0==wfmo)       
{
    printf("%s is done!\n", data[0].name);
    threads[0]=threads[1];
    data[0]=data[1];
    threads[1]=NULL;
}
else if ( WAIT_OBJECT_0 +1 == wfmo)     
{
    printf("%s is done!\n", data[1].name);

    threads[1]=NULL;
}

wfmo = WaitForMultipleObjects(1, threads, false, INFINITE);
if ( WAIT_OBJECT_0==wfmo)   
    printf("%s is done!\n", data[0].name);