【问题标题】:can I set a Task.WhenAll() result to a value within a Task.WhenAll() routine?我可以将 Task.WhenAll() 结果设置为 Task.WhenAll() 例程中的值吗?
【发布时间】:2018-12-17 14:43:34
【问题描述】:

我可以将 Task.WhenAll() 结果设置为 Task.WhenAll() 例程中的值吗?例如,以下代码将获取 appRoleMaps 中所有域/组组合的所有授权用户:

var results = await Task.WhenAll(appRoleMaps.Select(
    x => GetAuthorizedUsers(x.DomainName, x.ADGroupName)));

但是如果我想将每次迭代的授权用户结果设置为迭代项Authorized属性值呢?例如,类似下面的代码(虽然下面的代码不起作用):

var results = await Task.WhenAll(appRoleMaps.Select(
    x => x.AuthorizedUsers = GetAuthorizedUsers(x.DomainName, x.ADGroupName)));

有没有一种简化的方法来做到这一点?原因是,GetAuthorizedUsers 结果集不包括域/组信息,所以我不能只做一个简单的 foreach/where 最后通过此信息轻松加入

【问题讨论】:

  • 你能修改GetAuthorizedUsers()吗,如果是这样,让它创建包含域和组名的新对象。
  • 是的,我可以实现其他代码结构和解决方法,但我希望有一种更直接的方法来在 Task.WhenAll() 中设置这个值,这是我原来帖子的重点
  • WhenAll 在这里如何应用? appRoleMaps.Select 是否解析为任务列表?
  • @dlatikay 我通过 Select 根据每个 appRoleMap 的域名/组名选择授权用户
  • 啊,是的,现在我明白了,由于 lambda 中的分配不再等待,因此不适用于WhenAll。也许尝试使 lambda 表达式本身异步?

标签: c# .net parallel-processing async-await


【解决方案1】:

您可以创建一个异步 lambda 以传递给您的 Select。这将导致将每个结果分配给关联实例上的AuthorizedUsers 属性。外部的Task.WhenAll 只需要知道所有元素何时处理完毕。

await Task.WhenAll(appRoleMaps.Select(async x => 
    x.AuthorizedUsers = await GetAuthorizedUsers(x.DomainName, x.ADGroupName)));

【讨论】:

  • 对我来说似乎是一个很好的解决方案,一旦证明它可以编译并执行 OP 正在寻找的东西,我很乐意给你一个 +1
  • 原来写完后测试过;它确实编译。我记得my answer for a similar problem的模式。
  • 酷,我 +1。希望它可以解决 OP 的问题,但这是他们选择接受的答案。顺便说一句,谢谢你,没想到你可以做一个异步 llambda。
  • @RyanWilson:这是 MSDN 上的简短提及:Async Lambdas。它们的签名对应于Func<…,Task>Func<…,Task<TResult>>,因此可以将它们传递给接受参数等方法。
【解决方案2】:

保存任务,等待后查询:

var tasks = appRoleMaps.Select(x => GetAuthorizedUsers(x.DomainName, x.ADGroupName)).ToList();
await Task.WhenAll(tasks);
var results = tasks.Select(t => t.Result).ToList();

这比依赖副作用更干净。将值隐藏到某个属性中,然后再将其提取出来会混淆代码的含义,并且需要更多的代码工作。

【讨论】:

    猜你喜欢
    • 2014-06-04
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多