微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我使用以下方法异步并同时执行某些任务:
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会警告我整个方法将并行运行,因为方法内部没有等待调用.

我究竟做错了什么?

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

解决方法

再来一次:

如果我可以教人们关于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);
}

原文地址:https://www.jb51.cc/csharp/98482.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐