使用Task.WhenAll,或不使用Task.WhenAll
c#
我正在审查一些代码并试图提出一个技术原因,为什么您应该或不应该使用Task.WhenAll(Tasks[])并行进行 Http 调用。Http 调用调用不同的微服务,我猜其中一个调用可能需要也可能不需要一些时间来执行......(我想我对此并不感兴趣)。我正在使用 BenchmarkDotNet 来让我了解是否消耗了更多内存,或者执行时间是否有很大不同。以下是基准的过度简化示例:
[Benchmark]
public async Task<string> Task_WhenAll_Benchmark()
{
var t1 = Task1();
var t2 = Task2();
await Task.WhenAll(t1, t2);
return $"{t1.Result}===={t2.Result}";
}
[Benchmark]
public async Task<string> Task_KeepItSimple_Benchmark()
{
return $"{await Task1()}===={await Task2()}";
}
Task1和Task2方法真的很简单(我HttpClient在类中有一个静态)
public async Task<string> Task1()
{
using (var request = await httpClient.GetAsync("http://localhost:8000/1.txt"))
{
return $"task{await request.Content.ReadAsStringAsync()}";
}
}
public async Task<string> Task2()
{
using (var request = await httpClient.GetAsync("http://localhost:8000/2.txt"))
{
return $"task{await request.Content.ReadAsStringAsync()}";
}
}
还有我的结果
| 方法 | 意思 | 错误 | 标准差 | 第 0 代 | 第一代 | 第 2 代 | 已分配 |
|---|---|---|---|---|---|---|---|
| Task_WhenAll_Benchmark | 1.138 毫秒 | 0.0561 毫秒 | 0.1601 毫秒 | —— | —— | —— | 64 KB |
| Task_KeepItSimple_Benchmark | 1.461 毫秒 | 0.0822 毫秒 | 0.2331 毫秒 | —— | —— | —— | 64 KB |
回答
我的问题真的是,是否有技术原因为什么你应该或不使用 Task.WhenAll()?
在两个调用都失败的异常情况下,行为略有不同。如果await一次修改一次,则永远不会观察到第二次失败;第一次失败的异常会立即传播。如果使用Task.WhenAll,则观察到两种故障;两个任务都失败后会传播一个异常。
这只是一种偏好吗?
这主要只是偏好。我倾向于更喜欢,WhenAll因为代码更明确,但我一次await输入一个没有问题。
- @ADyson: Good point; they would be sequential then. My answer would be correct if the sample code was `return $"{await task1}===={await task2}";`