Основной поток создает несколько дополнительных. Дополнительные потоки выполняют некоторую работу и благополучно завершаются. Как основной поток может определить перед закрытием, что все дополнительные отработали? WaitForMultipleObjects(handles) не хотелось бы, т.к. неизвестно, сколько будет дополнительных потоков.
А в чем проблема с тем, что неизвестно заранее кол-во потоков? Храните в переменной их количество и хэндлы.
ОМГ, это как-то странно. Хэндл имеет размер 4 или 8 байт. Если сделать массив динамическим на памяти из кучи, через HeapAlloc / HeapRealloc, то туда можно такое количество хэндлов засунуть, сколько потоков вы точно не создадите...
Вот только реализации динамического массива из кучи мне не хватало :'( Тогда уж проще счетчик с критической секцией...
WaitForMultipleObjects максимальное количество хендлов для ожидания MAXIMUM_WAIT_OBJECTS = 64. Squash Счетчик потоков? ну всмысле семафор ...
Squash Судя по всему C++ - не ваша тема Сделайте статический массив заранее определенного размера, скажем на 64 килобайта. Больше потоков все равно нет смысла делать, комп захлебнется на переключении задач. А WaitForMultipleObjects не нужен - достаточно цикла из WaitForSingleObjects. PS. Еслечо: Код (Text): boost::thread_group threads. threads.create_thread(...); threads.create_thread(...); threads.create_thread(...); ... threads.join_all();
Ну ага, и цикл будет жрать процессорное время, когда часть потоков завершится, а часть ещё будет работать. Изначально тоже подумал о семафоре, забыл, что максимум 64 объекта можно ждать. Так что +1 shchetinin. Хотя, да, не сильно будет жрать, изредка подъедать =)
AtomicCounter вам в помощь. Семафор, то бишь Дополнительный поток стартует - INC, завершается - DEC. В основном потоке -- while (AtomicCounter) { Sleep(1); }
Мне семафор первым делом в голову пришел. Только что-то я никак не могу врубиться, как его использовать. Ворд Аутомейшн вчера взорвал мне мосх
Написано же - туплю. И потом, у него есть недостатки. В общем случае, основному потоку придется выполнять бесконечный цикл, периодически проверяя переменную.
Уважаемый shchetinin, не могли бы вы немного подробнее объяснить, как можно использовать семафор в данном конкретном случае?
Squash Почитайте про семафоры , там есть ReleaseSemaphore котый вернет счетчик , и это будет InerProc . Короче специально для ВАС псевдо убидый код построеный на EVENT (Для так будет проще) Код (Text): HANDLE g_SyncEvent = CreateEventW(NULL, TRUE, TRUE, NULL); DWORD g_SyncCounter = 0; void SomeSyncRef() { if ( 0 == g_SyncCounter ) { ResetEvent(g_SyncEvent); } ++g_SyncCounter; } void SomeSyncRelease() { --g_SyncCounter; if ( 0 == g_SyncCounter ) { SetEvent(g_SyncEvent); } } BOOL SomeSyncWait(DWORD dwWaitTimeout) { return WaitForSingleObject(g_SyncEvent, dwWaitTimeout) == WAIT_OBJECT_0 ? TRUE : FALSE; } Что сдесь сложного и не понятного?
А почему нельзя сначала посчитать кол-во необходимых потоков и только потом уже создавать их? Что за задача такая? Если потоки создаются только в точке входа процесса, где и происходит потом ожидание их завершения, то подсчитать необходимое их кол-во не должно вызывать никаких проблем. Если же дополнительные потоки могут порождать другие дополнительные потоки, то очевидно, стоит применить счётчик потоков и написать соответствующие функции типа Create/Delete, в Create - увеличивать счётчик, в Delete - уменьшать, при чём сразу после уменьшения проверять, если счётчик дошёл до нуля, то сигналить событие. Этого же события ждать перед выходом из точки входа. Я делал примерно также, когда надо было написать выгружаемый драйвер, который хукал много чего, - работало. Хотя для драйверов метод не 100% надёжный, сейчас другой использую, но тем не менее.
Для начала, мне непонятно, где здесь семафор. Количество потоков зависит от того, сколько раз пользователь - ну к примеру - кликнет по баттону. А, точно, к интерлоку добавить событие, тогда цикл не нужен. Хотя у меня можно и с циклом, основной поток начинает ждать дополнительные только при завершении. Все равно спасибо, пригодится на будущее.