这是相同(?)功能的三个版本
版本 1:
public async Task SomeMethodAsync(List<string> foos)
{
foreach(var foo in foos)
{
await SomeOtherMethodAsync();
}
DoSomethingElse();
}
版本 2:
public void SomeMethod(List<string> foos)
{
foos.ForEach(async foo => await SomeOtherMethodAsync());
DoSomethingElse();
}
版本 3:
public async Task SomeMethod(List<string> foos)
{
var tasks = foos.Select(foo => SomeOtherMethodAsync());
await Task.WhenAll(tasks);
DoSomethingElse();
}
为什么第一个版本需要将方法标记为异步才能在 foreach 循环内使用等待,而第二个版本不需要标记为异步(只是 Lambda 需要异步)。
第二个版本是否在 SomeMethod 退出之前等待循环内的所有 async/await 调用完成?我问这个是因为 SomeMethod() 不是异步的,它的调用者不会等待它。
第三个版本是否比版本 1 和 2 更受欢迎?
最佳答案
您的问题非常广泛,尤其是因为其中包含多个问题。但是,为了帮助……
- Why does this first version require the method to be marked async to use await inside the foreach loop vs the second version which doesn't need to be marked async (just the Lambda needs to be async).
方法必须标记为async
使用 await
.在您的第二个版本中,外部方法不使用 await
.只有在其中声明的匿名方法才可以。该匿名方法是一个完全不同的范围,并且使用 await
其中不涉及对外部方法的任何实际更改。在这方面,它们实际上是两个完全独立的方法声明。
- Does the second version wait for all the async/await calls inside the loop to complete before SomeMethod exits? I ask this because SomeMethod() is not async and it will not be awaited by it's caller.
第二个版本不是合法代码。没有 IList<T>.ForEach()
方法。我假设您的真实代码使用 List<T>.ForEach()
.考虑到这一点……
没有。您的第二个版本启动所有异步操作,然后返回。当您观察代码运行时,这应该已经很清楚了。
- Is the third version the preferred way over versions 1 & 2?
第三版不是合法代码。它不应该被标记为async
.但是,假设您的真实代码是正确的并且没有标记为 async
的方法……
“首选”见仁见智。然而,考虑到只有第三个版本同时运行所有操作并且提供了一种等待它们全部完成的机制,这显然是三个版本中最有用的.
- Is it just with the ForEach LINQ operator or does the same thing happen with other LINQ operators such as Where, Select etc?
(没有“ForEach LINQ 运算符”……见上文。)
“同样的事情”会发生吗?这完全取决于您如何使用它们。您已经有一个使用 Select()
的示例(您的第三个) , 并且工作方式不同。所以从这个意义上说,显然 “同样的事情” 不会发生。但在所有异步操作一起启动并且枚举可以在这些操作完成之前完成的意义上是相同的。
另一方面,ForEach()
方法是同步和即时的,而 LINQ 方法使用延迟执行。也就是说,它们创建了一个枚举对象,但在您实际使用该对象之前不会发生实际的枚举。
所以在你的第二个例子中,操作都是在 ForEach()
时开始的。方法返回。但在第三个示例中,它们直到您调用 WaitAll()
才开始。该方法枚举了您使用 Select()
创建的投影.
短语“同一件事” 没有明确定义,可能表示多种意思。如您所见,它在某些方面“相同”,而在其他方面“相同”。
关于c# - 在异步/等待方面,常规 foreach 和 ForEach LINQ 运算符有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45384963/