做毕业设计时要用到一个库
然后发现出现了一个没见过的类型IAsyncEnumerable
看着就跟异步有关,但直接await又直接报错
于是小研究了一下,感觉这玩意还挺有用的
<0x01> 什么是IAsyncEnumerable
从字面意思翻译,就是可枚举的异步
按官方的说法,这个是异步流
这是.net8.0加入的新的异步类型
可以实现流式异步
<0x02> 有什么用
这个类型的迭代器可以使用async/await关键字
实现迭代器中的异步
public static Task<string> IOBindingTask()
{
// 需要等待IO的任务
// 返回string
}
// 异步流迭代器
public static async IAsyncEnumerable<string> GetDataAsync()
{
yield return await IOBindingTask();
yield return await IOBindingTask();
yield return await IOBindingTask();
}
// 使用迭代器
public static async void UseData()
{
await foreach(var d in GetDataAsync())
{
Console.WriteLine(d);
}
}
这里给出一个例子
比如说我们需要从一个在线的API中获取一系列数据
长度不定,并且次返回数据都需要一点时间
按以前可以是这么写
public static Task<string>? GetData()
{
// 获取数据的方法,数据结尾返回null类型Task
// ...
}
public static IEnumerable<Task<string>> GetDataEnumerable()
{
var t = GetData();
while(t != null)
{
yield return t;
t = GetData();
}
}
public async void ProcessData()
{
// ...
foreach(Task<string> t in GetDataEnumerable())
{
string data = await t;
// ...
}
// ...
}
通过IAsyncEnumerable就可以这么写
public static Task<string> GetData()
{
// 获取数据的方法,数据结尾返回空字符串
// ...
}
public static async IAsyncEnumerable<string> GetFromWeb()
{
while(true)
{
var d = await GetData();
if(d == string.Empty)
{
yield break;
}
yield return d;
}
}
public async void ProcessData()
{
// ...
await foreach(var data in GetFromWeb())
{
// 处理data
}
// ...
}
通过IAsyncEnumerable可以更关注数据的处理,而不需要关心循环的问题
并且将异步等待放在迭代器中,这样调用时只需要处理最后的数据就可以
目前看这个异步流更像是语法糖,让异步获取多组数据更加优雅
之后有时间再研究研究,看看有没有别的细节不同