Csharp/C#教程:在LINQ语句中使用async / await时实际发生了什么?分享


在LINQ语句中使用async / await时实际发生了什么?

以下片段编译,但我希望它等待任务结果,而不是给我一个List<Task>

 var foo = bars.Select(async bar => await Baz(bar)).ToList() 

正如这里指出的,你需要使用Task.WhenAll

 var tasks = foos.Select(async foo => await DoSomethingAsync(foo)).ToList(); await Task.WhenAll(tasks); 

但是评论指出不需要在Select()内部进行asyncawait

 var tasks = foos.Select(foo => DoSomethingAsync(foo)).ToList(); 

这里有一个类似的问题,有人试图在Where()使用异步方法。

因此,在LINQ语句中asyncawait是合法的语法,但是它什么都不做或者它是否具有某种用途?

我建议您不要将其视为“在LINQ中使用async ”。 请记住两者之间的内容:代表。 几个LINQ运算符接受委托, async可用于创建异步委托。

所以,当你有一个返回Task的异步方法BazAsync

 Task BazAsync(TBar bar); 

然后这段代码会产生一系列任务:

 IEnumerable tasks = bars.Select(bar => BazAsync(bar)); 

同样,如果在委托中使用asyncawait ,则创建一个返回Task的异步委托:

 IEnumerable tasks = bars.Select(async bar => await BazAsync(bar)); 

这两个LINQ表达式在function上是等价的。 没有重要的区别。

就像常规的LINQ表达式一样, IEnumerable是惰性求值的。 只有像BazAsync这样的异步方法,你通常不需要意外的双重评估或类似的东西。 因此,当您投射到一系列任务时,立即重新确定序列通常是个好主意。 这为源序列中的所有元素调用BazAsync ,开始执行所有任务:

 Task[] tasks = bars.Select(bar => BazAsync(bar)).ToArray(); 

当然,我们用Select完成的所有事情都是为每个元素启动一个异步操作。 如果你想等待它们全部完成,那么使用Task.WhenAll

 await Task.WhenAll(tasks); 

大多数其他LINQ运算符不能与异步委托一起干净地工作。 Select非常简单:您只是为每个元素启动异步操作。

它有一定的用途吗?

当然。 使用async和await在LINQ语句中,您可以执行以下操作:

 var tasks = foos.Select( async foo => { var intermediate = await DoSomethingAsync( foo ); return await DoSomethingElseAsync( intermediate ); } ).ToList(); await Task.WhenAll(tasks); 

如果没有在LINQ语句中进行异步/等待,那么您不会在LINQ语句中等待任何内容,因此您无法处理结果或等待其他内容。

如果没有async / await,在LINQ语句中,您只是启动任务,而不是等待它们完成。 它们最终仍会完成,但是在控制将离开LINQ语句之后很久就会发生,所以你只能在WhenAll行完成后访问它们的结果,但不能在LINQ语句中访问它们。

上述就是C#学习教程:在LINQ语句中使用async / await时实际发生了什么?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ctvol.com/cdevelopment/999887.html

(0)
上一篇 2021年12月27日
下一篇 2021年12月27日

精彩推荐