2
votes

I'm trying to run 3 threads in the same time and then detect in main thread which one has finished. I'm using WaitForMultipleObject function but 3rd thread seems to loop for this WFMO function, while it has already finished its job (printed result).

    #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;
    }

Output:

    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!
2
Until you post threads code, it will be difficultYasir Majeed
There are only for loops where I multiple some vales x-times, and pprintf and the end. And return 0 ofc.orzel
It's doing exactly what you coded it to do. What's the mystery exactly?David Schwartz
@DavidSchwartz This really useful comment can answer 99% of questions on SO.ElderBug
@ElderBug Actually, I looked closely at the code and it's not quite as useful a comment as I originally thought.David Schwartz

2 Answers

1
votes

From the MSDN WaitForMultipleObjects documentation :

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.

Once the thread 0 is finished, the return value will always be WAIT_OBJECT_0.

0
votes

Solution (instead of while loop):

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);