Как бы я дождался остановки нескольких потоков? - PullRequest
8 голосов
/ 05 сентября 2010

У меня есть главный поток, который порождает около 20 рабочих потоков.
Мне нужно остановить основной поток, пока все остальные потоки не будут закончены.
Я знаю о (нить). Присоединяйтесь. Но это работает только для одного потока.

и несколько объединений снижают производительность, как это.

t1.Join ()
t2.Join ()
...
t20.Join ()

, поскольку программа ожидает один за другим для остановки.

Как бы я сделал так, чтобы основной поток ожидает завершения всех потоков?

Ответы [ 5 ]

11 голосов
/ 05 сентября 2010

Вы действительно должны взглянуть на Параллелизм задач (Task Parallel Library) . Он использует пул потоков, но также управляет кражей задач и т. Д.

Цитата: " TPL динамически масштабирует степень параллелизма, чтобы наиболее эффективно использовать все доступные процессоры. Кроме того, TPL обрабатывает разделение работы, планирование потоков в ThreadPool, поддержку отмены , управление состоянием и другие подробности низкого уровня. Task Parallel Library

Вы можете использовать это так:

Task[] tasks = new Task[3]
{
    Task.Factory.StartNew(() => MethodA()),
    Task.Factory.StartNew(() => MethodB()),
    Task.Factory.StartNew(() => MethodC())
};

//Block until all tasks complete.
Task.WaitAll(tasks);

Или, если вы используете какой-то цикл для создания своих потоков:

Параллелизм данных (библиотека параллельных задач)

4 голосов
/ 05 сентября 2010

С join все в порядке, если вы этого хотите. Основной поток все еще должен ждать завершения всех рабочих потоков. Проверьте этот веб-сайт, который является образцом главы от C# in a Nutshell. Так случилось, что это глава о потоках: http://www.albahari.com/threading/part4.aspx.

2 голосов
/ 05 сентября 2010

и несколько объединений снижают производительность как это.

Нет никакого «снижения производительности», если вы хотите дождаться завершения всех ваших потоков, вы вызываете .join () для потоков.

Заполните ваши темы в списке и сделайте

foreach(var t in myThread)
     t.join();
2 голосов
/ 05 сентября 2010

Я не вижу очевидного снижения производительности за ожидание завершения потоков один за другим.Итак, простой foreach делает то, что вы хотите, без лишних наворотов:

foreach (Thread t in threads) t.Join();

Примечание. Конечно, есть функция Win32 API, которая позволяет ожидать нескольких объектов (в данном случае потоков)сразу - WaitForMultipleObjectsEx.В Интернете существует множество вспомогательных классов или многопоточных сред, которые используют их для своих целей.Но действительно ли они нужны для простого случая?

1 голос
/ 05 сентября 2010

Если вы уверены, что у вас всегда будет <64 потоков, то каждый новый поток может надежно установить Событие до его выхода и WaitAll для событий в вашем основном потоке, как только все потоки будут запущены.Объект Event будет создан в главном потоке и передан соответствующему дочернему потоку потокобезопасным способом во время создания потока.</p>

В нативном коде вы можете сделать то же самое с самими обработчиками потоков, но не знаете, как это сделать в .Net.

См. Также предыдущий вопрос: C #: Ожиданиедля завершения всех потоков

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...