C # Параллельный тяжелый процесс

#c# #asynchronous #foreach #parallel-processing #queue

#c# #асинхронный #foreach #параллельная обработка #очередь

Вопрос:

Я должен выполнять метод ‘x’ раз параллельно.Этот метод в основном вызывает службы отчетов SQL Server для создания отчета, поэтому у меня есть список — скажем, 200 отчетов — для генерации.

Время, затрачиваемое методом (генерация отчета), зависит от полученных входных параметров: иногда это занимает 1 секунду, иногда 50 секунд, 2 минуты и т.д..

У меня есть коллекция отчетов для генерации ( _distinctReports ), поэтому я вызвал Parallel.ForEach отправку коллекции с a MaxDegreeOfParallelism = 8:

 Parallel.ForEach(_distinctReports, new ParallelOptions { MaxDegreeOfParallelism =  _maxDegreeOfParallelism }, ExecuteReport);
  

Я заметил, что каким-то Parallel.ForEach образом вызывает «пакеты» из 8 элементов одновременно (в зависимости от процессора сервера это может отличаться, но на сервере, который я тестирую, всегда обрабатывается 8) и отправляет еще один пакет из 8 только после завершения предыдущих 8, что является большой проблемой в моем случаепозвольте мне рассказать, почему:
Если пакет содержит 7 отчетов, сгенерированных за 1 секунду каждый, плюс один отчет за 2 минуты, мне нужно подождать целых 2 минуты, пока не будет запущен следующий пакет из 8 Parallel.ForEach .

Я хотел бы иметь очередь из 8 (другого желаемого количества), которая постоянно заполняется большим количеством элементов для обработки, как только появятся доступные слоты (а не блоки по 8).

Как я могу выполнить это на C #? Я читал об очередях, но не смог придумать дизайн, соответствующий моим требованиям.

Комментарии:

1. » Этот метод в основном вызывает службы отчетов SQL Server для создания отчета » Звучит так, как будто это должно быть асинхронным, а не параллельным. Это ExecuteReport async метод?

2. Нет не является асинхронным. Я рассматриваю этот вариант, но помните, что я не хочу, чтобы одновременно обрабатывалось более 8 отчетов

3. Параллелизм также async может быть ограничен. Если это процесс, который включает в себя ввод-вывод, то вы получите мало пользы от параллелизма.

4. Спасибо @JohnathanBarclay, я посмотрю. Более того, отчеты генерируются на другом сервере, и они обычно невелики по размеру, но логика извлечения данных на уровне SSRS может быть там очень медленной, поэтому не так много пользы в операциях ввода-вывода.

5. AFAIK Parallel.ForEach не ведет себя так, как вы описываете. Он ведет себя ожидаемым образом. Так что, вероятно, происходит что-то еще. Не могли бы вы попробовать вызвать ThreadPool.SetMinThreads(100, 100); в начале программы, чтобы убедиться, что вы не ограничены ThreadPool доступностью?