你如何异步地正确返回一组对象?

Dea*_*ane 3 .net c# system.reactive async-await entity-framework-core

我需要在核心界面中定义返回列表的方法.我的项目很大程度上依赖于使用async/await所以我需要将我的核心引用/接口定义为尽可能异步.我还将EF7用于我的数据访问层.我目前IAsyncEnumerable到处使用.

我目前正在决定是继续使用IAsyncEnumerable还是恢复使用Task<IEnumerable<T>>.IAsyncEnumerable在这一点上似乎很有希望.EF7也在使用它.麻烦的是,我不知道也无法弄清楚如何使用它.网站上几乎没有任何内容告诉任何人如何使用Ix.Net.有一个ToAsyncEnumerable我可以在IEnumerable对象上使用的扩展,但这不会异步做任何事情(或者它?).另一个缺点是给出以下签名:

IAsyncEnumerable GetPersons();
Run Code Online (Sandbox Code Playgroud)

因为这不是返回Task的函数,所以我不能在函数块中使用async/await.

另一方面,我的直觉告诉我,我应该坚持使用Task<IEnumerable<T>>.这当然也有它的问题.EF没有返回此类型的扩展方法.它有一个ToArrayAsyncToListAsync扩展方法,但当然,这需要你打电话等待方法中,因为Task<T>不是协变的.这可能是一个问题,因为这会产生额外的操作,如果我只是返回Task对象就可以避免这种操作.

我的问题是:我应该继续使用IAsyncEnumerable(首选)还是应该将所有内容更改回Task<IEnumerable<T>>(不是首选)?我也对其他建议持开放态度.

i3a*_*non 5

我会去IAsyncEnumerable.它允许您使您的操作保持异步和惰性.

没有它你需要返回Task<IEnumerble>,这意味着你将所有结果加载到内存中.在许多情况下,这意味着查询并保存比所需更多的内存.

经典案例是有一个用户调用的查询Any.如果它是,Task<IEnumerable>它将首先将所有结果加载到内存中,如果它正在IAsyncEnumerable加载一个结果就足够了.

同样重要的是,Task<IEnumerable>您需要同时在内存中保存整个结果集,同时IAsyncEnumerable您可以一次"流式"结果.

而且,这是生态系统走向的方向.它是由Stephen Toub本周建议新库通过反应式扩展添加的,并且可能会在下一版本的C#中本地支持.