c# - 异步任务被评估两次

标签 c# .net async-await

我使用下面的方法同时异步地做一些任务:

public async Task<Dictionary<string, object>> Read(string[] queries)
{
    var results = queries.Select(query => new Tuple<string, Task<object>>(query, LoadDataAsync(query)));

    await Task.WhenAll(results.Select(x => x.Item2).ToArray());

    return results
        .ToDictionary(x => x.Item1, x => x.Item2.Result);
}

我希望该方法同时为数组中的每个字符串调用 LoadDataAsync,然后等待所有任务完成并返回结果。

  • 如果我像这样运行方法,它会为每个项目调用两次 LoadDataAsync,一次在 await ... 行,一次在最后的 .Result 属性 getter 。
  • 如果我删除 await ... 行,Visual Studio 会警告我整个方法将并行运行,因为方法内部没有 await 调用.

我做错了什么?

有没有更好(更短)的方法来做同样的事情?

最佳答案

再一次:

如果我可以教人们关于 LINQ 的一件事,那就是查询的值是执行查询的对象,而不是执行查询的结果

您创建一次查询,生成一个可以执行查询的对象。然后执行查询两次。不幸的是,您创建了一个查询,它不仅计算一个值而且会产生副作用,因此,执行两次查询会产生两次副作用。 永远不要制作会产生副作用的可重用查询对象。查询是一种提问 的机制,因此得名。它们并非旨在成为一种控制流机制,但这正是您使用它们的目的。

执行查询两次会产生两个不同的结果,因为查询的结果在两次执行之间当然会发生变化。例如,如果查询正在查询数据库,则数据库可能在两次执行之间发生了变化。如果您的查询是“伦敦每位顾客的姓氏是什么?”答案可能从毫秒改变到毫秒,但问题保持不变。永远记住,查询代表一个问题

我会倾向于写一些没有疑问的东西。使用“foreach”循环产生副作用。

public async Task<Dictionary<string, object>> Read(IEnumerable<string> queries)
{
    var tasks = new Dictionary<string, Task<object>>();
    foreach (string query in queries)
        tasks.Add(query, LoadDataAsync(query));
    await Task.WhenAll(tasks.Values);
    return tasks.ToDictionary(x => x.Key, x => x.Value.Result);
}

关于c# - 异步任务被评估两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26124676/

相关文章:

rust - 如何在测试中运行并发任务? [复制]

c# - Linq to SQL 中的多值比较

c# - 找到最小的整数,当乘以一个已知的 double 时,将产生一个整数

c# - 使用子进程调试强大工具的混合模式调试 Python/C#

c# - 使用 OpenID 进行网站认证

C# async await Task.delay 实战

c# - 将 css 类名传递给 asp.mvc View 助手

c# - 对象与 SetValue 和枚举的目标类型不匹配

c# - 如何将 DispatcherObject (BitmapSource) 复制到不同的线程中?

c# - 带有 yield 返回的异步任务<IEnumerable>?