我正在开发一个 .NET Core 应用程序,我需要并行发出一堆 HTTP 请求。棘手的部分是,请求数量可能会有很大差异,具体取决于用户输入,有时只有 5 个,有时可能最多 50 个。
现在,我正在使用 Task.WhenAll 来处理它们,如下所示:
var tasks = urls.Select(url => httpClient.GetStringAsync(url)).ToArray();
var results = await Task.WhenAll(tasks);
这对于少量请求来说效果很好,但我担心当同时请求太多时应用程序会不堪重负。我还想确保如果一个请求超时或失败,其他请求仍然可以正常完成。
我想知道一些事情:
有没有办法限制同时运行的请求数量,比如一次 10 个?
如果其中一个请求花费的时间太长,我如何确保它超时而不影响其他请求?
重试失败的请求是个好主意,还是有更好的方法来处理?
我不确定 Task.WhenAll 是否是处理此问题的最佳方法,或者是否有更好的模式我应该考虑。任何建议都会很棒!
可能有很多方法可以做到这一点(PLINQ、带有 BulkHead 模式的 Polly,...)。与您的示例代码匹配的简单方法只需使用
SemaphoreSlim
var tasks = urls.Select(url => httpClient.GetStringAsync(url)).ToArray();
var results = await Task.WhenAll(tasks);
var semaphore = new SemaphoreSlim(5);
var tasks = urls.Select(async url =>
{
await semaphore.WaitAsync();
try
{
return await httpClient.GetStringAsync(url);
}
finally
{
semaphore.Release();
}
}).ToArray();
var results = await Task.WhenAll(tasks);
根据您的需求,您可能还应该考虑处理超时(提示:
CancellationTokenSource
)和重试失败的请求(Polly 库)