你如何異步地正確返回一組對象?


我需要在核心界面中定義返回列表的方法。我的項目很大程度上依賴於使用async / await所以我需要將我的核心引用/接口定義為盡可能異步。我還使用EF7作為我的數據訪問層。我目前在任何地方都使用IAsyncEnumerable

我目前正在決定是繼續使用IAsyncEnumerable還是恢復使用Task<IEnumerable<T>>IAsyncEnumerable在這一點上似乎很有希望。 EF7也在使用它。麻煩的是,我不知道也無法弄清楚如何使用它。 網站上幾乎沒有任何內容告訴任何人如何使用Ix.Net 。有一個ToAsyncEnumerable擴展,我可以在IEnumerable對像上使用,但這不會異步(或者它?)。另一個缺點是給出以下簽名:

IAsyncEnumerable GetPersons();

因為這不是返回Task的函數,所以我不能在函數塊中使用async / await。

另一方面,我的直覺告訴我,我應該堅持使用Task<IEnumerable<T>> 。這當然也有它的問題。 EF沒有返回此類型的擴展方法。它有一個ToArrayAsyncToListAsync擴展方法,但這當然要求你在方法內部調用await,因為Task<T>不是協變的。這可能是一個問題,因為這會創建一個額外的操作 ,如果我只返回Task對象就可以避免這種操作

我的問題是:我應該繼續使用IAsyncEnumerable (首選)還是應該將所有內容更改回Task<IEnumerable<T>> (不是首選)?我也對其他建議​​持開放態度。

熱門答案

我會選擇IAsyncEnumerable 。它允許您保持您的操作既異步又懶惰。

沒有它你需要返回Task<IEnumerble> ,這意味著你將所有結果加載到內存中。在許多情況下,這意味著查詢並保存比所需更多的內存。

經典案例是有一個用戶調用Any的查詢。如果它是Task<IEnumerable>它將首先將所有結果加載到內存中,如果它是IAsyncEnumerable加載一個結果就足夠了。

同樣相關的是,使用Task<IEnumerable>您需要同時在內存中保存整個結果集,而使用IAsyncEnumerable您可以一次“流式”化幾個結果。

而且,這是生態系統走向的方向。它是由Stephen Toub本周建議新庫通過反應式擴展添加的,並且可能會在下一版本的C#中本地支持





許可下: CC-BY-SA
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因