2016-08-06 3 views
2

Я новичок в параллельной библиотеке задач .NET Framework (и многозадачности и многопоточности в целом). Из литературы, которую я прочитал, я должен просто создать набор задач, запустить их, и структура должна позаботиться о появлении необходимого количества потоков в соответствии с ресурсами, доступными в системе. Проблема, с которой я сталкиваюсь, делает тысячи HTTP-запросов своевременно. Итак, это код, который у меня есть.Как сделать много запросов HTTP с помощью параллельной библиотеки задач

var taskList = new List<Task>(); 
foreach(var request in requests) 
{ 
    taskList.Add(client.SendAsync(request)); 
} 
Task.WaitAll(taskList.ToArray()); 

client является System.Net.Http.HttpClient объектом. Я использую Task.WaitAll(), потому что этот код находится внутри метода, который не является асинхронным. Чтобы проверить этот код, я делаю запросы на другой сервер в той же локальной сети. В коллекции запросов больше 15 000, поэтому задача должна быть создана для каждого объекта. Но ему удалось запустить только около 7000, прежде чем выбросить совокупное исключение. Внутреннее исключение, похоже, не очень полезно, указывая только «Задача была отменена» , хотя токен отмены сообщает, что никакой отмены не было запрошено. трассировка стека не очень полезно, либо с последних вызовов, показанными являются:

в System.Threading.Tasks.Task.WaitAll (Task [] задачи, Int32 millisecondsTimeout, CancellationToken CancellationToken) в системе .Threading.Tasks.Task.WaitAll (задачи [] задача, Int32 millisecondsTimeout)
на System.Threading.Tasks.Task.WaitAll (задание [] задача)

Я также играла с Parallel.Invoke(), но что оказалось намного хуже.

var taskActionList = new List<Action>(); 
foreach(var request in requests) 
{ 
    taskActionList.Add(() => client.SendAsync(request)); 
} 
Parallel.Invoke(taskActionList.ToArray()); 

Это не выбрасывает никаких исключений, но он работает только около 1300 задач и код выполняется до завершения.

Мой вопрос: как вы используете параллельную библиотеку задач для эффективного создания большого количества HTTP-запросов? Есть что-то, чего я не хватает?

+0

Я боюсь, что параллельная библиотека задач не имеет никакого отношения к подходу 'async-await', который вы пробовали. – Fabio

+0

Возможный дубликат [HttpClient - задача была отменена - как получить точное сообщение об ошибке?] (Http: // stackoverflow.com/questions/19120675/httpclient-task-was-cancell-how-to-get-the-exact-error-message) – Fabio

+0

Исключение, которое вы получаете, вероятно, связано с тем, что некоторые из запросов были отключены. Вы отправляете огромное количество запросов за очень короткое время, вы должны ожидать, что это произойдет. Что произойдет, если один запрос истечет? Кроме того, не следует ли ограничивать активное количество запросов в любой момент времени до разумного числа, например. 10? –

ответ

2

TPL не имеет понятия, как наилучшим образом планировать ваши HTTP-вызовы. Он даже не знает, что вы выполняете IO. Эвристика неадекватна.

Как правило, необязательная степень параллелизма для ввода-вывода должна определяться экспериментально. Вам нужно написать код, чтобы этот оптимальный DOP использовался. Ни одна из встроенных конструкций не может предоставить вам точную DOP. Это всегда максимум.

Здесь что-то перегружено, вызывая таймауты. Исключение отмены часто является признаком таймаута (да, это сомнительный дизайн API).

Для этого можно использовать ForEachAsync.

requests.ForEachAsync(async() => await ProcessAsync(request)).Wait(); 
Смежные вопросы