#c#
#c#
Вопрос:
В консольном приложении я запускаю параллель для каждого цикла в другом цикле, но одно из моих обновлений может занять 10 минут, а остальные — всего 1 секунду. Это означает, что 99 выполнено, но он ожидает завершения 1 оставшегося, прежде чем запустить следующий пакет.
List<Items> myItems = GetItems();
while (myItems.Count > 0)
{
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 100;
Parallel.ForEach(myItems, options, item => {
CallUpdate(item.ID);
});
// Get some more records and loop
myItems = GetItems()
}
Есть ли лучший способ сделать это так, чтобы 100 потоков всегда могли выполняться, пока существуют некоторые элементы?
Комментарии:
1. для чего нужен внешний цикл while? Что происходит внутри GetItems()?
2. Если задача связана с вводом-выводом, у нее больше потоков, чем ядер. Если привязан к процессору, потоков должно быть не больше, чем ядер.
3. Почему вас волнует, если вы держите все потоки занятыми? Знаете ли вы, какое обновление занимает много времени? Если вы это сделаете, запланируйте это отдельно (возможно, в потоке, не относящемся к пулу потоков). Вы также можете уменьшить свой параллелизм (чтобы 99 элементов выполнялись в более неторопливом темпе — не нужно спешить, если вы все равно собираетесь ждать). Как бы то ни было, вы, вероятно, обнаружите, что не выполняете работу со всеми потоками, которые, по вашему мнению, используете
4. @MikeJ Он просто получает пакеты элементов для работы, которые еще не были обработаны. Таким образом, вместо того, чтобы получать 10 миллионов элементов одновременно, он будет делать это меньшими партиями по 100, чтобы коллекция myItems не занимала много памяти.
5. @feijoc вероятно, лучше разбить его на каждый шаг и применить соответствующее решение, если это шаг, связанный с вводом-выводом, например, ожидание вызова DB, затем используйте async / await, если это интенсивный процессорный шаг, затем распараллеливайте. Также попытайтесь найти узкие места без асинхронной или параллельной обработки — это может дать представление о том, какие шаги занимают больше времени.
Ответ №1:
То, что вы описываете, довольно хорошо подходит для реализации шаблона производителя / потребителя. Вы можете создать простую реализацию этого шаблона с помощью BlockingCollection
Но если сложность возрастает, то, вероятно, лучшим выбором будет что-то вроде TPL. Вот пример для производителя / потребителя, использующего TPL.