Я пытаюсь запустить 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
документация :
Если bWaitAll имеет значение FALSE, возвращаемое значение минус WAIT_OBJECT_0 указывает индекс массива lpHandles объекта, который удовлетворил ожидание. Если более одного объекта стало сигнализироваться во время вызова, это индекс массива сигнализируемого объекта с наименьшим значением индекса из всех сигнализируемых объектов.
Как только поток 0 закончен, возвращаемое значение всегда будет 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);