Я прочитал все связанные вопросы в SO, но немного запутался в лучшем подходе для моего сценария, когда запускается несколько вызовов веб-службы.
У меня есть служба-агрегатор, которая принимает входные данные, анализирует и переводит их в несколько веб-запросов, выполняет вызовы веб-запросов (несвязанные, поэтому их можно запускать параллельно) и объединяет ответ, который отправляется обратно вызывающей стороне. Следующий код используется прямо сейчас -
list.ForEach((object obj) =>
{
tasks.Add(Task.Factory.StartNew((object state) =>
{
this.ProcessRequest(obj);
}, obj, CancellationToken.None,
TaskCreationOptions.AttachedToParent, TaskScheduler.Default));
});
await Task.WhenAll(tasks);
await Task.WhenAll(tasks)
взят из сообщения Скотта Хансельмана, где говорится, что
По словам Стивена, лучшим решением с точки зрения масштабируемости является использование преимуществ асинхронного ввода-вывода. Когда вы звоните по сети, нет причин (кроме удобства) блокировать потоки в ожидании ответа.
Существующий код потребляет слишком много потоков, а процессорное время достигает 100 % при производственной нагрузке, и это заставляет меня задуматься.
Другой альтернативой является использование Parallel.ForEach, который использует разделитель, но также блокирует вызов, что подходит для моего сценария.
Учитывая, что это все работа с асинхронным вводом-выводом, а не работа, связанная с процессором, а веб-запросы выполняются недолго (возврат максимум через 3 секунды), я склонен полагать, что существующий код достаточно хорош. Но обеспечит ли это лучшую пропускную способность, чем Parallel.ForEach? Parallel.ForEach, вероятно, использует минимальное количество задач из-за разделения и, следовательно, оптимального использования потоков (?). Я протестировал Parallel.ForEach с некоторыми локальными тестами, и он не стал лучше.
Цель состоит в том, чтобы сократить время ЦП и увеличить пропускную способность и, следовательно, лучшую масштабируемость. Есть ли лучший подход для параллельной обработки веб-запросов?
Ценим любые материалы, спасибо.
EDIT: метод ProcessRequest, показанный в примере кода, действительно использует HttpClient и его асинхронные методы для отправки запросов (PostAsync, GetAsync, PutAsync).
ProcessRequest
использует асинхронные методы, почему вы вызываете их внутриTask.Factory.StartNew
? Вы можете просто добавить задачу, которую он возвращает, в свой список. Если вы на самом деле блокируете его внутри, не имеет значения, что вы используете асинхронные методы в его частях. Последний блокирующий вызов сводит на нет все преимущества - person Panagiotis Kanavos   schedule 05.06.2015