.NET — IAsyncEnumerable 实用工具扩展

💡 原文中文,约14200字,阅读约需34分钟。
📝

内容提要

在.NET Core 3中引入了异步流的概念,通过接口表示,并在C# 8中直接支持。Microsoft标准化了.NET开发人员实现异步流的方式。文章介绍了一些常见的情况和解决方法,包括异步流的实用程序扩展、超时处理、批处理和节流。这些方法可以帮助开发人员更好地处理异步流操作。

🔎

延伸解读

扩展方法的设计准则:输入验证与取消令牌

文章强调,为 IAsyncEnumerable<T> 编写扩展方法时,应避免在公共方法签名中直接进行参数验证,而是通过包装方法在内部实现中验证,以保持堆栈跟踪清晰。同时,推荐使用 [EnumeratorCancellation] 属性而非在签名中显式传递 CancellationToken,这样编译器会自动将取消令牌传递给所有异步迭代方法,减少调用方的困惑。这些准则有助于编写更健壮、易维护的异步流扩展。

超时处理:防止无限期等待

从异步流接收数据时,可能无法预知总耗时,但可以强制每个项目之间的最大等待时间。文章展示了通过链接 CancellationTokenSource 并设置 CancelAfter 来实现超时,在等待下一项时若超时则抛出 TaskCanceledException。另一种实现可手动遍历枚举器,在捕获到 TaskCanceledException 且外部未取消时抛出 TimeoutException,使超时语义更明确。这种方法适用于需要实时响应的场景,如 LLM API 的流式响应。

批处理优化:减少数据库访问

当从数据库读取大量数据并需要存储时,逐项操作会导致频繁的数据库访问,影响性能。文章提供了 Batch 扩展方法,将项目按指定大小分批返回,从而减少访问次数。还支持超时参数,在等待超时后返回已接收的部分批次,避免长时间等待。实现仅使用一个 DateTime 计算超时,高效且易于理解,但需注意超时仅在收到项目后检查,而非在等待时触发。

节流控制:防止应用过载

在高吞吐量场景下,为防止应用程序过载,文章介绍了 Throttling 扩展方法。它通过计算下一次允许处理的时间,并在必要时使用 Task.Delay 延迟,确保项目以可控的节奏被消费。该方法常与超时和批处理结合使用,以强制数据的预测节奏。实现简单,仅需维护一个 DateTime 变量,适合需要限制处理速率的场景。

❓

Q&A

.NET中的异步流是什么?

.NET中的异步流是通过IAsyncEnumerable接口实现的,允许异步地处理数据流。

如何在异步流中实现超时处理?

可以通过创建一个CancellationTokenSource并在指定时间后取消操作,从而实现超时处理。

批处理在异步流中的作用是什么?

批处理可以减少数据库访问次数,提高性能,通过将多个项目一起处理来优化插入操作。

节流在异步流中如何应用?

节流通过限制项目的处理速率,防止在高吞吐量情况下使应用程序过载。

在实现异步流扩展时需要遵循哪些准则?

应避免在方法中验证函数输入,而是创建包装器方法进行验证,以保持堆栈跟踪的清晰。

如何使用LINQ方法处理异步流?

可以使用LINQ扩展方法,如Where、Batch和Timeout,来处理异步流中的数据。

🏷️

标签

➡️

继续阅读