.NET Core 3.0中IAsyncEnumerableT有什么大不了的?
.NET Core 3.0和C# 8.0最激動人心的特性之一就是IAsyncEnumerable<T>(也就是async流)。但它有什么特別之處呢?我們現在可以用它做哪些以前不可能做到的事?
在本文中,我們將了解IAsyncEnumerable<T>要解決哪些挑戰,如何在我們自己的應用程序中實現它,以及為什么IAsyncEnumerable<T>將在很多情況下取代Task<IEnumerable<T>>。
也許最好的證明IAsyncEnumerable < T >有用的方式是看看在沒有它的時候所面臨的的困難。
比如首先有這樣一段代碼,按頁面獲取所有喜歡的帖子:
public async Task<IEnumerable<Post>> GetPagePostsFromLikes(int pageNumber){
// 實現省略
}
然后有另一段代碼調用上面這段代碼:
public async Task<IEnumerable<Post>> GetAllPostsFromLikes(){
var allPosts = new List<Post>();
for (int page = 0; ; page++)
{
var posts = await GetPagePostsFromLikes(page);
if (!posts.Any())
{
return allPosts;
}
allPosts.AddRange(posts);
}
}
注意,上面這個方法有一個問題,我們對每個頁面的結果進行循環并放入List<Post>中,最后返回整個結果。假設有上億個page頁面的的帖子,那么所有這上億個page頁面的帖子都需要在返回值之前被加載。顯然是非常低效的。
也許我們可以不使用Task來替換上面的方法:
public IEnumerable<Post> GetAllPostsFromLikes(){
for (int page = 0; ; page++)
{
var posts = GetPagePostsFromLikes(page).GetAwaiter().GetResult();
if (!posts.Any())
{
yield break;
}
foreach (var post in posts)
{
yield return post;
}
}
}
在上面代碼中,返回IEnumerable<T>的方法可以使用yield return語句將每個數據片段返回給調用者。
但是,請勿這樣做!?上面的代碼意味著如果我們從異步方法中調用第三個函數,線程池將持續迭代返回的IEnumerable,直到其完成,也就是說當有足夠多的并發訪問同一個線程,勢必會造成阻塞。
?如果我們可以用異步方法來使用yield return就好了!可惜那是不可能的……直到現在。
?這個時候IAsyncEnumerable<T> 就該出場啦!!!!!!
IAsyncEnumerable<T>是在.NET Core 3 (.NET Standard 2.1)引入的。它公開了一個枚舉器,該枚舉器具有可以等待的MoveNextAsync()方法。這意味著生產者可以在產生結果之間進行異步調用。
與返回任務<IEnumerable<T>>不同,我們的方法現在可以返回IAsyncEnumerable<T>,并使用yield return來發送數據:
public async IAsyncEnumerable<Post> GetAllPostsFromLikes(){
for (int page = 0; ; page++)
{
var posts = GetPagePostsFromLikes(page).GetAwaiter().GetResult();
if (!posts.Any())
{
yield break;
}
foreach (var post in posts)
{
yield return post;
}
}
}
為了使用結果,我們需要使用c# 8中新的await foreach()語法:
await foreach (var post in postsRepository.GetAllPostsFromLikes()){
Console.WriteLine(post);
}
這個好多了。該方法生成可用的數據。調用代碼以自己的節奏使用數據。
?
從.NET Core 3.0 Preview 7 開始,ASP.NET就能夠從API控制器動作中返回IAsyncEnumerable<T>,這意味著我們可以直接返回方法的結果——有效地將數據從數據庫流到HTTP響應。
[HttpGet]public IAsyncEnumerable<Post> Get()
=> postsRepository.GetAllPostsFromLikes();
隨著時間的推移,隨著.NET Core3.0和.NET Standard2.1的發展,我們將會看到IAsyncEnumerable<T>被用在我們通常使用Task<IEnumerable<T>>的地方。
總結
IAsyncEnumerable<T>是. net的一個很受歡迎的新特性,在很多情況下,它可以使代碼更簡潔、更高效。
想要了解更多,請參考以下資源:
Tutorial: Generate and consume async streams using C# 8.0 and .NET Core 3.0
C# language proposals - Async Streams
new features in .NET Core 3
總結
以上是生活随笔為你收集整理的.NET Core 3.0中IAsyncEnumerableT有什么大不了的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用FastReport报表工具生成报表
- 下一篇: 致所有.Net者和有梦想的朋友们 - 共