异步流——创建异步流
问题
假设需要返回多个值,而且需要对每个值执行一些异步处理。
– 通过IEnumerable<T>返回多个值,然后对其进行异步处理
– 通过Task<T>异步返回单个值,然后添加的其他的返回值
解决方案
通过yield return 可以从一个方法返回多个值,而异步方法使用async和await。在使用异步流时,可以将这两者合并。只用IAsyncEnumerable<T>的返回类型:
async IAsyncEnumerable<int> GetValueAsync()
{
await Task.Delay(1000);//异步处理
yield return 10;
await Task.Delay(1000);//更多异步处理
yield return 13;
}
在下面这个更切合实际的实例中,API使用了分页参数,该实例异步枚举了API的所有返回结果
async IAsyncEnumerable<string> GetValuesAsync(HttpClient client)
{
int offset=0;
const int limit=10;
while(true)
{
string result =await client.GetStringAsync($"https://exampleurl/api/values?offset={offset}&limit={limit}");
string[] valuesOnThisPage=result.Split("\n");
foreach(string value in valuesOnThisPage)
{
yield return value;
}
if(valuesOnThisPage.Length!=limit)
{
break;
}
offset+=limit;
}
}
讨论
对异步流而言,这是一种常规模式,对许多流而言,大多数异步迭代其实是同步的,异步流只是允许一步获取下一项而已。不论异步流获取项的方式是同步还是异步,由于其实质上使用了ValueTask<T>,因此异步流的效率都得以最大化。
在实现异步流时,可以考虑支持取消操作。可以通过CancellationToken支持恰当的取消功能。