.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 = ; ; 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 = ; ; 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 = ; ; 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的一个很受欢迎的新特性,在很多情况下,它可以使代码更简洁、更高效。

想要了解更多,请参考以下资源:

.NET Core 3.0中IAsyncEnumerable<T>有什么大不了的?的更多相关文章

  1. 【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  2. [转]【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  3. ASP.NET Core 1.0 中的依赖项管理

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  4. 在ASP.NET Core 1.0中如何发送邮件

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:目前.NET Core 1.0中并没有提供SMTP相关的类库,那么要如何从ASP.NE ...

  5. EF Core 1.0中使用Include的小技巧

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:由于EF Core暂时不支持Lazy Loading,所以利用Include来加载额外 ...

  6. ASP.NET Core 1.0 中使用 Swagger 生成文档

    github:https://github.com/domaindrivendev/Ahoy 之前文章有介绍在ASP.NET WebAPI 中使用Swagger生成文档,ASP.NET Core 1. ...

  7. 用ASP.NET Core 1.0中实现邮件发送功能

    准备将一些项目迁移到 asp.net core 先从封装类库入手,在遇到邮件发送类时发现在 asp.net core 1.0中并示提供SMTP相关类库,于是网上一搜发现了MailKit 好东西一定要试 ...

  8. Core 1.0中的管道-中间件模式

    ASP.NET Core 1.0中的管道-中间件模式 SP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middlewar ...

  9. Entity Framework Core 2.0 中使用LIKE 操作符

    Entity Framework Core 2.0 中使用LIKE 操作符 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译 ...

随机推荐

  1. java中父类子类静态代码块、构造代码块执行顺序

    父类静态(代码块,变量赋值二者按顺序执行) 子类静态 父类构造代码块 父类构造方法 子类构造代码块 子类构造方法 普通方法在实列调用的时候执行,肯定位于上面之后了 //父类A public class ...

  2. Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵动态限流规则

    Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵动态限流规则 前面几篇文章较为详细的介绍了Sentinel的使用姿势,还没看过的小伙伴可以访问以下链接查看: &l ...

  3. STL目录

    觉得STL有必要讲一下,毕竟STL包含的东西太又用了. STL(Standard Template Library)这个玩意是啥,怎么来的之类的我就不说了,百度上一大推. 我就说一下ACM或者OI中会 ...

  4. SpringCloud学习笔记(7):使用Spring Cloud Config配置中心

    简介 Spring Cloud Config为分布式系统中的外部化配置提供了服务器端和客户端支持,服务器端统一管理所有配置文件,客户端在启动时从服务端获取配置信息.服务器端有多种配置方式,如将配置文件 ...

  5. [Pandas] 03 - DataFrame

    DataFrame 表格基本操作 初始化 一并设置 index & columns 类似于倒排表,column相当于words. index就是doc id. df = pd.DataFram ...

  6. gitbook 入门教程之还在搞公众号互推涨粉?gitbook 集成导流工具,轻轻松松躺增粉丝!

    相信大多数博客作者都或多或少有过这样想法: 现在各种平台这么多,想要实现全平台发布就要到处复制粘贴,等我有空一定做统一平台一次性全部解决! 不知道正在阅读文章的你,有没有这样的想法? 反正我确实这么想 ...

  7. java Mail如何发送邮件

    1.应用场景:在系统需要发送与用户相关的消息时,而用户不在线,可以采取发送邮件的方式,使用户了解最新的系统情况 或者发送验证码等验证场景 2.实验环境 主要使用mail.jar和activation. ...

  8. 第八届蓝桥杯java b组第一题

    1,标题: 购物单    小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞.    这不,XX大促销又来了!老板夫人开出了长长的购 ...

  9. Python学习笔记整理总结【Django】:Model操作(二)

    1.操作汇总 # 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj = models ...

  10. 一行命令安装docker和docker-compose(CentOS7)

    想快速装好docker和docker-compose ?那就随本文用一次复制粘贴来完成安装: 环境信息 操作系统:CentOS Linux release 7.7.1908 (Core, 操作账号:r ...