Asynchronous 使用不同结果类型时,在dotnet core中使用Task.whall的最佳实践
我有一些工作代码。但我不完全确定在处理Task.WhenAll时,最佳实践是什么。我发现不同的博客帖子使用了不同的方法,但没有一篇说明为什么他们使用了自己的方法。我发现的唯一“好”帖子是使用Task.WhenAll获取类似的数据并合并结果。但我的用例是我需要处理几个数据源,这些数据源具有不同的数据 我采用的方法是:Asynchronous 使用不同结果类型时,在dotnet core中使用Task.whall的最佳实践,asynchronous,.net-core,async-await,Asynchronous,.net Core,Async Await,我有一些工作代码。但我不完全确定在处理Task.WhenAll时,最佳实践是什么。我发现不同的博客帖子使用了不同的方法,但没有一篇说明为什么他们使用了自己的方法。我发现的唯一“好”帖子是使用Task.WhenAll获取类似的数据并合并结果。但我的用例是我需要处理几个数据源,这些数据源具有不同的数据 我采用的方法是: var weatherTask = GetWeatherAsync(); var locationTask = GetLocationAsync(); var driversTask
var weatherTask = GetWeatherAsync();
var locationTask = GetLocationAsync();
var driversTask = GetDriversAsync();
await Task.WhenAll(weatherTask, locationTask, driversTask)
var weather = await weatherTask;
var location = await locaitonTask;
var drivers = await driversTask;
主要是因为我喜欢它的外观/可读性。但我也考虑过使用以下其他方法:
var weatherTask = GetWeatherAsync();
var locationTask = GetLocationAsync();
var driversTask = GetDriversAsync();
await Task.WhenAll(weatherTask, locationTask, driversTask)
var weather = weatherTask.Result;
var location = locaitonTask.Result;
var drivers = driversTask.Result;
这种方法背后的思想是,任务已经完成,使用.Result可以保存。但我坚持第一种方法。因为我不完全确定“等待”(如果有的话)的开销
所以我来到这里,希望一些聪明人知道答案
***编辑
我看过
这篇文章的答案是:
您还可以使用Task.Result(因为此时您知道它们都已成功完成)。然而,我建议使用wait,因为它显然是正确的,而结果可能会在其他场景中导致问题
但如果有任何性能,就不能使用一个而不是另一个
********编辑
把这个例子发挥到极致。看看这两个循环
for(int i=0; i< 1.000.000.000; i++)
{
var weatherTask = GetWeatherAsync();
var locationTask = GetLocationAsync();
var driversTask = GetDriversAsync();
await Task.WhenAll(weatherTask, locationTask, driversTask)
var weather = await weatherTask;
var location = await locaitonTask;
var drivers = await driversTask;
}
for(int i=0;i<1.000.000.000;i++)
{
var weatherTask=GetWeatherAsync();
var locationTask=GetLocationAsync();
var driversTask=GetDriversAsync();
等待任务。WhenAll(天气任务、位置任务、驾驶员任务)
var weather=等待weatherTask;
var位置=等待位置任务;
var drivers=等待driversTask;
}
vs
for(int i=0;i<1.000.000.000;i++)
{
var weatherTask=GetWeatherAsync();
var locationTask=GetLocationAsync();
var driversTask=GetDriversAsync();
等待任务。WhenAll(天气任务、位置任务、驾驶员任务);
var weather=weatherTask.Result;
变量位置=LocationTask.Result;
var drivers=driversTask.Result;
}
他们两个会一样快吗?或者任务。结果会快得多吗?所以我做了一个不完全准确的测试。但给了我一个小小的指标来说明我的期望 守则: 在for循环中运行10次后的结果: 等待总是稍微慢一点。但不多。对于1.000.000来说,这不是一个太大的问题。但如果您的量表高于此值,则在Task.whalll之后使用.Result可能是一个好主意:)
此测试在未关闭浏览器、visual studio和其他应用程序的情况下运行。因此,这绝不是一个干净的测试。只是一个不使用BenchmarkDotnet的快速尝试可能更像是最差的而不是最佳的实践,但它似乎是一个可行的选择
var weatherTask = Task.FromResult(new Weather());
var locationTask = Task.FromResult(new Location());
var driversTask = Task.FromResult(new Driver[0]);
var results = await Task.WhenAll(
Task.Run(async () => await weatherTask as object),
Task.Run(async () => await locationTask as object),
Task.Run(async () => await driversTask as object));
var weather = (Weather)results[0];
var location = (Location)results[1];
var drivers = (Driver[])results[2];
这回答了你的问题吗?你好它没有:)我已经看到了那个问题。但它没有足够详细地说明为什么它是正确的解决方案:)为什么不?使用
wait
更合适,因为.Result
在特定场景中可能会导致死锁。有关更多信息,请参阅“在特定情况下可能导致死锁”。我知道这一点。但在这种情况下并非如此。我完全知道我不应该在一个尚未等待的任务上使用.Result。我的问题是,我什么时候等待了一整张任务清单。使用.Result是否会有任何性能,而wait(一项已经完成的任务)可能会有一些开销。如果您对性能优化感兴趣,那么我认为使用.Result
将比使用wait
子句更快。这是因为wait
强制编译器在处理异常时使用状态机来形成正确的调用堆栈。
var weatherTask = Task.FromResult(new Weather());
var locationTask = Task.FromResult(new Location());
var driversTask = Task.FromResult(new Driver[0]);
var results = await Task.WhenAll(
Task.Run(async () => await weatherTask as object),
Task.Run(async () => await locationTask as object),
Task.Run(async () => await driversTask as object));
var weather = (Weather)results[0];
var location = (Location)results[1];
var drivers = (Driver[])results[2];