什么是IAsyncEnumerable

IAsyncEnumerable<T> 是 .NET 中用于表示异步数据流的接口。

它允许你逐个异步地获取数据项,而不是将所有数据一次性加载到内存中。这样可以减少内存占用,尤其在处理大量数据时更加高效。

与 IEnumerable<T> 不同,IEnumerable<T> 是同步的,要求所有数据在返回之前就加载完成。

而 IAsyncEnumerable<T> 是异步的,支持在数据流被请求时逐步加载,适合处理从数据库或网络等源异步获取的数据。

示例:

public async IAsyncEnumerable<int> GetNumbersAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(100); // 模拟异步操作
yield return i;
}
}

好处

减少内存占用:IAsyncEnumerable<T> 逐步加载数据,避免了需要将所有数据一次性加载到内存中。对于大数据量的查询,能显著减少内存压力。

提升响应性能:在 WebAPI 中,返回 IAsyncEnumerable<T> 可以让客户端在获取部分数据时立即开始处理,而无需等待所有数据都加载完成。这使得响应时间更短,提升用户体验。

避免阻塞操作:使用 async/await 使得 WebAPI 不会被同步阻塞操作所拖慢,能够更好地处理并发请求。

以 WebAPI + EFCore 举例

假设我们需要通过 Entity Framework Core 从数据库中查询大量记录。

如果我们一次性加载所有数据,可能会导致内存占用过高,甚至影响性能。使用 IAsyncEnumerable<T>,我们可以逐个获取数据。

示例代码:

public class ProductController : ControllerBase
{
private readonly ApplicationDbContext _context; public ProductController(ApplicationDbContext context)
{
_context = context;
} [HttpGet("products")]
public async IAsyncEnumerable<Product> GetProductsAsync()
{
await foreach (var product in _context.Products.AsAsyncEnumerable())
{
yield return product;
}
}
}

在这个例子中,AsAsyncEnumerable() 方法将 DbSet<Product> 转换成一个异步数据流,await foreach 循环逐个从数据库中异步获取数据并返回,避免了内存占用过多。

以 WebAPI + HTTPClient 举例

在 WebAPI 中,你可能需要调用其他服务或外部 API 来获取数据。使用 IAsyncEnumerable<T> 可以使得调用返回的数据逐步加载,避免等待整个请求完成后再返回。

示例代码:

public class ExternalApiController : ControllerBase
{
private readonly HttpClient _httpClient; public ExternalApiController(HttpClient httpClient)
{
_httpClient = httpClient;
} [HttpGet("external-data")]
public async IAsyncEnumerable<string> GetExternalDataAsync()
{
var response = await _httpClient.GetAsync("https://api.example.com/data");
response.EnsureSuccessStatusCode(); var stream = await response.Content.ReadAsStreamAsync();
using (var reader = new StreamReader(stream))
{
string? line;
while ((line = await reader.ReadLineAsync()) != null)
{
yield return line;
}
}
}
}

在这个例子中,我们通过 HTTPClient 请求外部 API 数据,并使用 IAsyncEnumerable<string> 返回每一行数据,允许客户端逐步处理数据,而无需等待所有数据都加载完毕。

客户端怎么处理 IAsyncEnumerable<T>

客户端接收到 IAsyncEnumerable<T> 数据流后,可以使用异步迭代器 await foreach 来逐步处理数据。

这样可以在数据流逐步传输过程中及时处理和显示数据,而不必等待全部数据加载完成。

C# 客户端代码:
public class ProductClient
{
private readonly HttpClient _httpClient; public ProductClient(HttpClient httpClient)
{
_httpClient = httpClient;
} public async Task GetProductsAsync()
{
var response = await _httpClient.GetAsync("https://example.com/products");
response.EnsureSuccessStatusCode(); await foreach (var product in response.Content.ReadFromJsonAsync<IAsyncEnumerable<Product>>())
{
Console.WriteLine(product.Name);
}
}
}
JavaScript 客户端处理:

在 JavaScript 中,客户端可以使用 fetch API 和流(Streams)来逐步处理数据。WebAPI 返回的数据流可以通过 Response.body.getReader() 来读取并逐步消费。

async function fetchProducts() {
const response = await fetch('https://example.com/products');
const reader = response.body.getReader();
const decoder = new TextDecoder();
let done = false;
let value = ''; while (!done) {
const { done: chunkDone, value: chunk } = await reader.read();
done = chunkDone;
value += decoder.decode(chunk, { stream: true });
console.log(value); // 逐步输出数据
}
}

通过上述方式,JavaScript 客户端可以逐步处理 WebAPI 返回的异步流,提升用户体验和响应速度。

.NET最佳实践:webapi返回IAsyncEnumerable提升性能的更多相关文章

  1. 十个 JDBC 的最佳实践

    JDBC是Java为多种关系型数据库提供的统一的访问接口,以下是我长期使用JDBC总结的十个最佳实践. 1. 使用PrearedStatement 任何一个使用过JDBC的Java程序员几乎都知道这个 ...

  2. web移动开发最佳实践之html篇

    一.前言 在目前的移动应用开发大潮下,使用web技术进行移动应用开发正变得越来越流行,它主要使用html5.css3.js等技术,在跨平台性.可移植性方面具有无可比拟的优势,特别适合开发对性能要求不太 ...

  3. XPages访问关系型数据库技术与最佳实践

    XPage 对于 Domino 开发人员的一大好处就是能够很方便和高效的访问关系型数据库.本文通过实例代码展现了在 XPage 中访问关系型数据库的具体步骤 , 同时讲解了一些在 XPage 中高效访 ...

  4. TOP100summit:【分享实录-华为】微服务场景下的性能提升最佳实践

    本篇文章内容来自2016年TOP100summit华为架构部资深架构师王启军的案例分享.编辑:Cynthia 王启军:华为架构部资深架构师.负责华为的云化.微服务架构推进落地,前后参与了华为手机祥云4 ...

  5. paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah

    paip.提升性能--多核编程中的java .net php c++最佳实践  v2.0 cah 作者Attilax  艾龙,  EMAIL:1466519819@qq.com  来源:attilax ...

  6. MySQL性能优化的21个最佳实践

    http://www.searchdatabase.com.cn/showcontent_38045.htm MySQL性能优化的21个最佳实践 1. 为查询缓存优化你的查询 大多数的MySQL服务器 ...

  7. http网页性能最佳实践

    你愿意为打开一个网页等待多长时间?我一秒也不愿意等.但是事实上大多数网站在响应速度方面都让人失望.现在越来越多的人开始建立自己的网站,博客,你的网页响应速度如何呢?在这篇文章中我们来介绍一下提高网页性 ...

  8. Mysql数据库调优和性能优化的21条最佳实践

    Mysql数据库调优和性能优化的21条最佳实践 1. 简介 在Web应用程序体系架构中,数据持久层(通常是一个关系数据库)是关键的核心部分,它对系统的性能有非常重要的影响.MySQL是目前使用最多的开 ...

  9. ASP.NET Core 性能优化最佳实践

    本文提供了 ASP.NET Core 的性能最佳实践指南. 译文原文地址:https://docs.microsoft.com/en-us/aspnet/core/performance/perfor ...

  10. Atitit.列表页面and条件查询的实现最佳实践(1)------设置查询条件and提交查询and返回json数据

    Atitit.列表页面and条件查询的实现最佳实践(1)------设置查询条件and提交查询and返回json数据 1. 1. 配置条件字段@Conditional 1 1 2. 2. 配置条件字段 ...

随机推荐

  1. Redis中的分布式锁(步步为营)

    分布式锁 概述 分布式锁指的是,所有服务中的所有线程都去获取同一把锁,但只有一个线程可以成功的获得锁,其他没有获得锁的线程必须全部等待,直到持有锁的线程释放锁. 分布式锁是可以跨越多个实例,多个进程的 ...

  2. Think in Java之构造器的真正调用顺序

    构造器是OOP的重要组成部分,很多人认为它很容易.只不过是new了一个对象而已.而think in java的作者却告诉我们,其实这并不容易.先看下面这个例子.在你没看结果之前,你觉得你的答案是对的么 ...

  3. Windows下的终端工具-Terminal

    文档:https://docs.microsoft.com/zh-cn/windows/terminal/ Windows 终端是一个面向命令行工具和 shell(如命令提示符.PowerShell ...

  4. mysqldump+binlog备份脚本

    mysqldump是一种逻辑备份工具 , 可以对数据库进行全量备份 , 和binlog增量备份共同使用可以进行数据库备份 , 基于此写了一个备份的脚本 #!/bin/bash all_path=&qu ...

  5. 全球气象数据ERA5的下载方法

      本文介绍在ERA5气象数据的官方网站中,手动下载.Python代码自动批量下载逐小时.逐日与逐月的ERA5气象数据各类产品的快捷方法.   ERA5(fifth generation ECMWF ...

  6. DOM元素高度获取踩坑

    前情 最近在开发一个需求,需要做一个滚动列表展示当前中奖用户,但是列表每一项高度又不是固定的,每次滚动前需要先获取当前要滚动的块是多高才知道要滚动多少. 坑位 在开发这个滚动列表的时候发现滚着滚着就会 ...

  7. Windows更改远程桌面端口

    为了远程安全,默认在3389改为别的端口. 本示例为3389改为53389 1.步骤:打开"开始→运行",输入"regedit",打开注册表,进入以下路径: [ ...

  8. docker containner挂掉,无法exec进入bash,如何修改文件的终极解决方法

    场景: Nginx在bash里面配置的时候挂掉了,然后docker start不起来,exec bash进不去,造成无法再改里面的文件了 解决方法: 1,docker ps –a 可以查到所有dock ...

  9. ChatGPT生成接口测试用例(二)

    5.1.4 自动生成测试数据 测试数据的生成通常是接口测试的一个烦琐任务.ChatGPT可以帮助测试团队生成测试数据,包括各种输入和它们的组合.测试人员可以描述他们需要的数据类型和范围,ChatGPT ...

  10. 【C语言】【二级】移动一维数组中的内容;若数组中有n个整数,要求把下标从0到p的数组元素平移到数组的最后

    题目 请编写函数fun,函数的功能是:移动一维数组中的内容;若数组中有n个整数,要求把下标从0到p(含p, p小于等于n-1)的数组元素平移到数组的最后. 例如,一维数组中的原始内容为:1,2,3,4 ...