C# IAsyncEnumerable Linq使用
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);
}
当然可以使用扩展
public static async Task<List<T>> AsListAsync<T>(this IAsyncEnumerable<T> source, CancellationToken cancellationToken = default)
{
var list = new List<T>();
await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
{
list.Add(item);
} return list;
}
从.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
- https://docs.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8
如果你要在Linq中使用s ystem.Linq.Async在System.Reactive包的名称空间中。如果您不需要完整的System.Reactive软件包,则可以直接使用System.Linq.Async软件包(是的一部分System.Reactive)。
您可以阅读此github问题。的来源System.Linq.Async可以在这里找到。
首先安装Nuget
github https://github.com/dotnet/reactive 得lx.Async 得system.linq.async



C# IAsyncEnumerable Linq使用的更多相关文章
- C#8.0: 在 LINQ 中支持异步的 IAsyncEnumerable
C# 8.0中,提供了一种新的IAsyncEnumerable<T>接口,在对集合进行迭代时,支持异步操作.比如在读取文本中的多行字符串时,如果读取每行字符串的时候使用同步方法,那么会导致 ...
- Linq表达式、Lambda表达式你更喜欢哪个?
什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- [C#] 走进 LINQ 的世界
走进 LINQ 的世界 序 在此之前曾发表过三篇关于 LINQ 的随笔: 进阶:<LINQ 标准查询操作概述>(强烈推荐) 技巧:<Linq To Objects - 如何操作字符串 ...
- [C#] 进阶 - LINQ 标准查询操作概述
LINQ 标准查询操作概述 序 “标准查询运算符”是组成语言集成查询 (LINQ) 模式的方法.大多数这些方法都在序列上运行,其中的序列是一个对象,其类型实现了IEnumerable<T> ...
- LINQ to SQL语句(7)之Exists/In/Any/All/Contains
适用场景:用于判断集合中元素,进一步缩小范围. Any 说明:用于判断集合中是否有元素满足某一条件:不延迟.(若条件为空,则集合只要不为空就返回True,否则为False).有2种形式,分别为简单形式 ...
- .NET深入实战系列—Linq to Sql进阶
最近在写代码的过程中用到了Linq查询,在查找资料的过程中发现网上的资料千奇百怪,于是自己整理了一些关于Linq中容易让人困惑的地方. 本文全部代码基于:UserInfo与Class两个表,其中Cla ...
- LINQ Group By操作
在上篇文章 .NET应用程序与数据库交互的若干问题 这篇文章中,讨论了一个计算热门商圈的问题,现在在这里扩展一下,假设我们需要从两张表中统计出热门商圈,这两张表内容如下: 上表是所有政区,商圈中的餐饮 ...
- Entity Framework 6 Recipes 2nd Edition(11-9)译 -> 在LINQ中使用规范函数
11-9. 在LINQ中使用规范函数 问题 想在一个LINQ查询中使用规范函数 解决方案 假设我们已经有一个影片租赁(MovieRental )实体,它保存某个影片什么时候租出及还回来,以及滞纳金等, ...
随机推荐
- LIS问题$n log_2 n$做法(二分优化)
#include<bits/stdc++.h> using namespace std; const int inf=1e9+5; const int maxn=1e6+5; int n, ...
- 【初等数论】裴蜀定理&扩展欧几里得算法
裴蜀定理: 对于\(a,b\in N^*, x, y\in Z\),方程\(ax+by=k\)当且仅当\(gcd(a, b)|k\)时有解. 证明: 必要性显然. 充分性:只需证明当\(k=gcd(a ...
- Codeforces Round #677 (Div. 3)
F. Zero Remainder Sum || dp #include <cstdio> #include <algorithm> #include <cstring& ...
- Access数据库简介
一.Access数据库的简介 1.microsoft office access是由微软发布的关联式数据库管理系统.它结合了 microsoft jet database engine 和 图形用户界 ...
- charles 常用功能 (六)抓包结果列表指展示关注的接口(focus on 功能)
添加关注的接口 2.启用关注接口,添加过滤的地址 3.重新抓包结果 不在上一步配置中的接口,都会隐藏在other host中
- springmvc<三> 异常解析链与视图解析链
1.1.7. Exceptions - 如果异常被Controller抛出,则DispatchServlet委托异常解析链来处理异常并提供处理方案(通常是一个错误的响应) spri ...
- 老猿学5G扫盲贴:与用户和终端相关的名词UE、SUPI、GPSI、PEI
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 和4 ...
- PyQt(Python+Qt)学习随笔:QListWidget删除项的takeItem方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 takeItem方法从QListWidget列表部件的项中删除指定项,并返回对应项对象.调用语法如下 ...
- x++ 和 ++x的区别
很多编程语言都会有x++和++x的问题,两个到底是怎么回事? 一个先执行一个后执行的区别 var x = 0; console.log(x++);//0 遇到x++当前执行值不变 console.lo ...
- 网络层-network layer(下):网络互连、子网掩码计算方法、Ipv4报头解析
第五章 网络层-Network Layer(下) 上一章讲了网络层的任务.提供的两种服务.五个重要的路由算法.以及网络层的拥塞控制和服务质量问题.这一部分主要讲一讲网络互连问题和Internet的网络 ...