Asynchronous 使用不同结果类型时,在dotnet core中使用Task.whall的最佳实践

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

我有一些工作代码。但我不完全确定在处理Task.WhenAll时,最佳实践是什么。我发现不同的博客帖子使用了不同的方法,但没有一篇说明为什么他们使用了自己的方法。我发现的唯一“好”帖子是使用Task.WhenAll获取类似的数据并合并结果。但我的用例是我需要处理几个数据源,这些数据源具有不同的数据

我采用的方法是:

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];