use*_*702 25 c# linq asynchronous c#-5.0
以下片段编译,但我希望它等待任务结果,而不是给我一个List<Task<T>>.
var foo = bars.Select(async bar => await Baz(bar)).ToList()
Run Code Online (Sandbox Code Playgroud)
正如这里指出的,你需要使用Task.WhenAll:
var tasks = foos.Select(async foo => await DoSomethingAsync(foo)).ToList();
await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)
但评论指出,不需要内部async和await内部Select():
var tasks = foos.Select(foo => DoSomethingAsync(foo)).ToList();
Run Code Online (Sandbox Code Playgroud)
这里有一个类似的问题,有人试图在其中使用异步方法Where().
因此async,await在LINQ语句中是合法的语法,但它什么都不做或者它有特定的用途?
Ste*_*ary 31
我建议您不要将其视为" async在LINQ中使用".请记住两者之间的内容:代表.几个LINQ运算符接受委托,async可用于创建异步委托.
所以,当你有一个异步方法BazAsync返回一个Task:
Task BazAsync(TBar bar);
Run Code Online (Sandbox Code Playgroud)
那么这段代码会产生一系列任务:
IEnumerable<Task> tasks = bars.Select(bar => BazAsync(bar));
Run Code Online (Sandbox Code Playgroud)
同样,如果在委托中使用async和,则await创建一个返回以下内容的异步委托Task:
IEnumerable<Task> tasks = bars.Select(async bar => await BazAsync(bar));
Run Code Online (Sandbox Code Playgroud)
这两个LINQ表达式在功能上是等效的.没有重要的区别.
就像常规的LINQ表达式一样,它IEnumerable<Task>是惰性求值的.只是,与异步方法一样BazAsync,你通常不希望意外双重评价或类似的东西.因此,当您投射到一系列任务时,立即重新确定序列通常是个好主意.这将调用BazAsync源序列中的所有元素,开始执行所有任务:
Task[] tasks = bars.Select(bar => BazAsync(bar)).ToArray();
Run Code Online (Sandbox Code Playgroud)
当然,我们所做的Select就是为每个元素启动一个异步操作.如果你想等待它们全部完成,那么使用Task.WhenAll:
await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)
大多数其他LINQ运算符不能与异步委托一起干净地工作.Select非常简单:您只是为每个元素启动异步操作.
它有一定的用途吗?
当然.使用async并等待LINQ语句内部,您可以执行以下操作:
var tasks = foos.Select( async foo =>
{
var intermediate = await DoSomethingAsync( foo );
return await DoSomethingElseAsync( intermediate );
} ).ToList();
await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)
如果没有在LINQ语句中进行异步/等待,那么您不会在LINQ语句中等待任何内容,因此您无法处理结果或等待其他内容.
没有async/await,在LINQ语句中,您只是启动任务,而不是等待它们完成.它们最终仍然会完成,但是在控制将离开LINQ语句之后很久就会发生,所以你只能WhenAll在行完成之后访问它们的结果,但不能在LINQ语句中访问它们.
| 归档时间: |
|
| 查看次数: |
10745 次 |
| 最近记录: |