Мне нужно создать неизвестное количество потоков, и в конце нужно ждать, пока все созданные потоки закончат свои задания. После поиска я мог подождать только некоторое количество созданных потоков, используя WaitForMultipleObjects(...)
который ожидает указатель на массив дескрипторов созданных потоков. Следующий пример - пример сценария.
#include "stdafx.h"
#include <Windows.h>
#include <time.h>
FILE* fp;
time_t start;
struct mydata{
int a, b;
};
void myFn(mydata* p)
{
fprintf(fp, "a = %d\n", p->a);
fprintf(fp, "b = %d\n", p->b);
delete p;
}
bool condition()
{
if(time(0) - start >= 1)
return false;
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
start = time(0);
fopen_s(&fp, "outOfExe.txt", "w");
mydata* dataToGive;
int n = 0;
while(condition())
{
n++;
dataToGive = new mydata;
dataToGive->a = 2*n;
dataToGive->b = 4*n;
HANDLE WINAPI handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)myFn, dataToGive, 0, NULL);
}
}
Решение, о котором я мог думать, состоит в создании массива размера, равного количеству ядер в ЦП, и в любой момент времени выполняется с максимальным количеством этих потоков. Но для этого мне потребуется разработать механизм очередей и т.д. Есть ли способ подождать все созданные потоки, как показано в приведенном выше примере?
int threadCount, критический раздел, событие и WaitForSingleObject?
Заблокируйте CS, создайте свои потоки, нарисуйте threadCount, затем откройте CS и подождите события.
В функции/методе потока выполните свои действия, затем, в конце, заблокируйте CS, отмените threadCount. Если он равен 0, сообщите об этом событии. Разблокируйте CS и выйдите из потока.
Нет массива, нет вектора, нет, (нормальный), ограничение количества потоков.
Использование std::vector
- это, безусловно, способ сделать и не требует очереди или имеет заданное количество ручек потоков, которые он может хранить. В приведенном ниже коде будут созданы все потоки, а затем дождаться завершения всех этих действий.
std::vector<HANDLE> threadHandles;
while(condition())
{
n++;
dataToGive = new mydata;
dataToGive->a = 2*n;
dataToGive->b = 4*n;
HANDLE handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)myFn, dataToGive, 0, NULL);
if(handle != INVALID_HANDLE_VALUE)
{
threadHandles.push_back(handle);
}
}
::WaitForMultipleObjects(threadHandles.size(), &threadHandles[0], TRUE, INFINITE);
Как заметил Мартин WaitForMultipleObjects
ограничивает количество дескрипторов, на которые он может ждать до 64. Если вам нужно больше 64 потоков, это не сработает.