Выполнение большого количества одновременных удаленных вызовов API должно выполняться аккуратно, поскольку вы можете исчерпать пул соединений. Я предлагаю подход с SemaphoreSlim
для выполнения регулирования и Channel
для использования ответов потокобезопасным способом.
var batches = Enumerable.Range(0, 1000);
var responseCh = Channel.CreateUnbounded<string>();
var throttler = new SemaphoreSlim(10);
var requestTasks = batches.Select(async batch =>
{
await throttler.WaitAsync();
try
{
var result = await MakeHttpRequestAsync(batch);
await responseCh.Writer.WriteAsync(result);
}
finally
{
throttler.Release();
}
}).ToArray();
var requestProcessing = Task.Run(async () =>
{
await Task.WhenAll(requestTasks);
responseCh.Writer.Complete();
});
var responseProcessing = Task.Run(async () =>
{
await foreach (var res in responseCh.Reader.ReadAllAsync())
Console.WriteLine(res); // or store in a data structure
});
await Task.WhenAll(requestProcessing, responseProcessing);
Мы ограничиваем запросы, не допуская более 10 одновременно. , Мы запускаем их одновременно и в момент прибытия пишем ответ на канал. Мы обрабатываем ответы в отдельном потоке, читая их из канала. Обработка запросов и ответов происходит одновременно, поэтому мы асинхронно ожидаем завершения их обоих.
Обратите внимание, что интерфейс IAsyncEnumerable
(await foreach
) доступен в C# 8, и каналы поставляются с. NET Core 3.1 SDK или вы можете найти их в NuGet .