IAsyncEnumerable:用 await foreach 写出更省内存的流式处理

作者:微信公众号:【架构师老卢】
2-1 10:21
40

IAsyncEnumerable<T> 解决的是一个很现实的问题:

我不想等“全部取完”才开始处理,我想边拿边算

典型场景:

  • 从数据库分页/游标读取
  • 从 HTTP 持续拉取数据
  • 从消息队列消费

基本用法

public async IAsyncEnumerable<int> GetNumbersAsync(
    [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct = default)
{
    for (var i = 0; i < 10; i++)
    {
        ct.ThrowIfCancellationRequested();
        await Task.Delay(50, ct);
        yield return i;
    }
}

await foreach (var n in GetNumbersAsync(ct))
{
    Console.WriteLine(n);
}

常见坑

  1. 忘了取消:流式处理通常是长任务,务必把 CancellationToken 一路传下去。

  2. 误以为并发await foreach 默认是串行消费;需要并发要自己做 Channel / Task.WhenAll + 限流。

  3. 资源释放:如果你的迭代器内部打开连接/流,确保在迭代结束时能正确释放(await using / try/finally)。

什么时候不该用

  • 数据量很小、一次性加载更简单
  • 需要随机访问(IAsyncEnumerable 是顺序流)

参考链接

  • Iterators with async streams:https://learn.microsoft.com/dotnet/csharp/iterators#async-iterators
  • IAsyncEnumerable 接口:https://learn.microsoft.com/dotnet/api/system.collections.generic.iasyncenumerable-1
相关留言评论
昵称:
邮箱:
阅读排行