C#等待X和.Result在ToDictionary()中不等效?

时间:2020-05-20 08:34:21

标签: c# async-await

我想在一堆ToDictionary上使用Task<MyObject>(请参见下文)。如果我使用TheTask.Result,但不等待

这有效:

Dictionary<CarId, Task<Model>> allModelTasks = carIds.ToDictionary(cId =>cId, cId=> GetModelForCar(cId));                                  
await Task.WhenAll(allModelTasks.Values);
Dictionary<CarId, Model> allModels = allModelTasks.ToDictionary(mt => mt.Key, mt => mt.Value.Result);

但是如果我将最后一行替换为

Dictionary<CarId, Model> allModels = allModelTasks.ToDictionary(mt => mt.Key, async mt => await mt.Value);

我收到一条错误消息,内容为“无法从Dict<CarId, Task<Model>>转换为Dict<CarId, Model>”。 如我所见,这些行应该等效。

(建议from here似乎是使用await代替.Result,即使在 EDIT Task.WhenAll之后)

1 个答案:

答案 0 :(得分:8)

您似乎忽略了能够在最后一行中写await,还必须添加另一个async。这意味着await不在您当前的方法中-它位于新的async lambda中,当然,被async返回的是Task

您不能在此处的lambda中使用await,并且期望没有任务要展开。您的第一个代码很好,并且不会遇到访问.Result可能引起的任何潜在问题,因为众所周知Task已经完成。


您可以创建或复制某种形式的ToDictionaryAsync扩展方法到您的类中,例如:

public static class TaskResultExtensions
{
    public static async Task<Dictionary<TKey, TValue>> ToDictionaryAsync<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, Task<TValue>>> source)
    {
        var dict = new Dictionary<TKey, TValue>();
        foreach (var kvp in source)
        {
            dict.Add(kvp.Key, await kvp.Value);
        }

        return dict;
    }
}

然后允许您使用最后一行

Dictionary<CarId, Model> allModels = await allModelTasks.ToDictionaryAsync();

相反。