Мне нужно извлечь контент из примерно 3000 URL. Я использую HttpClient
, создаю Task
для каждого URL, добавляю задачи в список и затем await Task.WhenAll
. Примерно так
var tasks = new List<Task<string>>();
foreach (var url in urls) {
var task = Task.Run(() => httpClient.GetStringAsync(url));
tasks.Add(task);
}
var t = Task.WhenAll(tasks);
Однако многие задачи оказываются в состояниях Faulted
или Canceled
. Я думал, что это может быть проблема с конкретными URL, но нет. Я могу получить эти URL без проблем с curl параллельно.
Я пробовал HttpClientHandler
, WinHttpHandler
с различными таймаутами и c. Всегда несколько сотен URL заканчиваются ошибкой. Затем я попытался получить эти URL в партиях по 10, и это работает. Без ошибок, но очень медленно. Curl будет очень быстро получать 3000 URL параллельно. Затем я попытался httpbin.org 3000 раз проверить, что проблема не в моих конкретных URL:
var handler = new HttpClientHandler() { MaxConnectionsPerServer = 5000 };
var httpClient = new HttpClient(handler);
var tasks = new List<Task<HttpResponseMessage>>();
foreach (var _ in Enumerable.Range(1, 3000)) {
var task = Task.Run(() => httpClient.GetAsync("http://httpbin.org"));
tasks.Add(task);
}
var t = Task.WhenAll(tasks);
try { await t.ConfigureAwait(false); } catch { }
int ok = 0, faulted = 0, cancelled = 0;
foreach (var task in tasks) {
switch (task.Status) {
case TaskStatus.RanToCompletion: ok++; break;
case TaskStatus.Faulted: faulted++; break;
case TaskStatus.Canceled: cancelled++; break;
}
}
Console.WriteLine($"RanToCompletion: {ok} Faulted: {faulted} Canceled: {cancelled}");
Опять же, всегда несколько сотен задач заканчиваются ошибкой.
Итак, в чем здесь проблема? Почему я не могу получить эти URL с помощью async
?
, который я использую. NET Core и, следовательно, предложение использовать ServicePointManager ( Попытка запустить несколько HTTP-запросов параллельно, но ограничена Windows (реестр) ) не применимо.
Кроме того, URL-адреса, которые мне нужно получить, указывают на разные хосты. Код с httpbin - это всего лишь тест, показывающий, что проблема не в том, что мои URL-адреса неверны.