Задать вопрос

Как правильно дождаться выполнения всех потоков, созданных в цикле?

Пожалуйста. подскажите:
Есть потоки, создаваемые в цикле. Все они должны выполняться параллельно, но при этом дальнейшее выполнение кода после потока должно происходить только по завершении всех этих потоков.
Код примерно такой:

List<Thread> lstThread = new List<Thread>();
 while (currentItemMonth <= this.lastMonth)
{

                            GeneratorItemSheet g = new GeneratorItemSheet(sh);
                            Thread myThread = new Thread(new ThreadStart(g.GenerateMonthSheet));
                            myThread.Start();
                            lstThread.Add(myThread);

                            //Переходим на следующий месяц
                            currentItemMonth = currentItemMonth.AddMonths(1);
}

foreach (Thread thread in lstThread)
{
      if (thread.IsAlive) thread.Join();
}


Т е складываю все потоки в лист, а потом циклом делаю им join.
Вопрос: Правильный ли это способ или надо как-то иначе. Просто у меня уходит в зависание, понять бы, это оттого, что идея в принципе неправильная или идея правильная, но хромает реализация внутри метода, вызываемого в потоке.
  • Вопрос задан
  • 4262 просмотра
Подписаться 5 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 3
@kttotto
пофиг на чем писать
У Вас не правильный подход. Во первых забудьте про Thread и используйте TPL. Во вторых для распараллеливания запросов в цикле есть замечательный метод Parallel.ForEach. В третьих для ожидания выполнения всех параллельных задач есть Task.WaitAll.
В общем Вы можете создать список Task-ов и запихнуть их в Task.WaitAll, но лучше пройдитесь параллельным форичем по Вашему периоду и внутри запускайте Ваши методы. Код за форичем будет ожидать завершения всех потоков в цикле.
Ответ написан
tomnolane
@tomnolane
профессиональный разработчик
оффтоп
люди подписались чисто поглазеть или поржать?

вы уверены, что вам нужен Thread?
Task или Thread в C#.NET 4.0 WPF? ( Павел Елизарьев доступно описал разницу в ответе)
я бы использовал Task для начала, т.к. есть такая замечательная штука, как пулл потоков (подзабыл как на английском называется) который лучше обычного программиста (автоматически) понимает, когда и кто закончил, сколько есть свободных, сколько нужно и что с ним дальше делать. И нужно у вас в коде делать акцент не на блокирование/синхронизацию потоков (оставьте их в покое - чем быстрее сделают, тем лучше), а использовать вот такую простую штуку: Оператор lock
а зависание происходит потому, что вы и основной поток блокируете.
Ключевое слово lock не позволит ни одному потоку войти в важный раздел кода в тот момент, когда в нем находится другой поток. При попытке входа другого потока в заблокированный код потребуется дождаться снятия блокировки объекта.
Ответ написан
AlexanderYudakov
@AlexanderYudakov
C#, 1С, Android, TypeScript
Написано все правильно.

Чтобы понять, в чем проблема, давайте попробуем внутри метода "GenerateMonthSheet" вывести в лог две записи: начало работы, окончание работы (с указанием месяца).

И посчитаем, сколько стартануло, сколько завершило работу.

P.S. А как вы номер месяца в генератор передаете? И откуда берется переменная "sh"?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы