跳到主要内容

C# 异步流

介绍

在 C# 中,异步编程是一种处理长时间运行操作的方式,而异步流(Async Streams)则是异步编程的扩展,允许我们以异步的方式处理数据流。异步流特别适用于处理大量数据或需要等待数据到达的场景,例如从网络或数据库中读取数据。

C# 8.0 引入了异步流,通过 IAsyncEnumerable<T> 接口和 await foreach 语法,我们可以轻松地处理异步数据流。

异步流的基本概念

IAsyncEnumerable<T> 接口

IAsyncEnumerable<T> 是一个异步版本的 IEnumerable<T>,它允许我们以异步的方式枚举数据流。与 IEnumerable<T> 不同,IAsyncEnumerable<T>MoveNextAsync 方法返回一个 Task<bool>,表示是否还有更多的数据可以异步获取。

await foreach 语法

await foreach 是用于遍历 IAsyncEnumerable<T> 的语法。它允许我们在每次迭代时异步等待下一个数据项。

代码示例

以下是一个简单的异步流示例,展示了如何生成和消费异步流。

csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program
{
static async Task Main(string[] args)
{
await foreach (var number in GenerateNumbersAsync())
{
Console.WriteLine(number);
}
}

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

输出:

0
1
2
3
4
5
6
7
8
9

在这个示例中,GenerateNumbersAsync 方法返回一个 IAsyncEnumerable<int>,它每秒生成一个数字。Main 方法使用 await foreach 来异步遍历这些数字并打印出来。

实际应用场景

从数据库中读取数据

假设我们有一个数据库,其中包含大量数据。我们可以使用异步流来逐步读取数据,而不是一次性将所有数据加载到内存中。

csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program
{
static async Task Main(string[] args)
{
await foreach (var record in ReadRecordsFromDatabaseAsync())
{
Console.WriteLine(record);
}
}

static async IAsyncEnumerable<string> ReadRecordsFromDatabaseAsync()
{
// 模拟从数据库中读取数据
for (int i = 0; i < 100; i++)
{
await Task.Delay(100); // 模拟异步操作
yield return $"Record {i}";
}
}
}

输出:

Record 0
Record 1
Record 2
...
Record 99

处理实时数据流

异步流还可以用于处理实时数据流,例如从传感器或网络接收数据。

csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program
{
static async Task Main(string[] args)
{
await foreach (var data in ReceiveRealTimeDataAsync())
{
Console.WriteLine($"Received: {data}");
}
}

static async IAsyncEnumerable<string> ReceiveRealTimeDataAsync()
{
while (true)
{
await Task.Delay(500); // 模拟异步操作
yield return $"Data at {DateTime.Now}";
}
}
}

输出:

Received: Data at 10/15/2023 12:00:00 PM
Received: Data at 10/15/2023 12:00:01 PM
Received: Data at 10/15/2023 12:00:02 PM
...

总结

异步流是 C# 中处理异步数据流的强大工具,特别适用于处理大量数据或需要等待数据到达的场景。通过 IAsyncEnumerable<T>await foreach,我们可以轻松地生成和消费异步流。

附加资源

练习

  1. 修改 GenerateNumbersAsync 方法,使其生成斐波那契数列。
  2. 创建一个异步流,模拟从 API 中分页获取数据,并打印每一页的内容。