c# - 使用 IAsyncEnumerable 读取文本文件
问题描述
我在测试 C# 8.0 功能时遇到了 IAsyncEnumerable。我从 Anthony Chu ( https://anthonychu.ca/post/async-streams-dotnet-core-3-iasyncenumerable/ ) 那里找到了一些非凡的例子。它是异步流和替代Task<IEnumerable<T>>
// Data Access Layer.
public async IAsyncEnumerable<Product> GetAllProducts()
{
Container container = cosmosClient.GetContainer(DatabaseId, ContainerId);
var iterator = container.GetItemQueryIterator<Product>("SELECT * FROM c");
while (iterator.HasMoreResults)
{
foreach (var product in await iterator.ReadNextAsync())
{
yield return product;
}
}
}
// Usage
await foreach (var product in productsRepository.GetAllProducts())
{
Console.WriteLine(product);
}
我想知道这是否可以应用于读取文本文件,如下面的逐行读取文件的用法。
foreach (var line in File.ReadLines("Filename"))
{
// ...process line.
}
我真的很想知道如何将 async withIAsyncEnumerable<string>()
应用于上述 foreach 循环,以便它在阅读时流式传输。
如何实现迭代器,以便可以使用 yield return 逐行读取?
解决方案
完全一样,但是没有异步工作负载,所以让我们假设
public async IAsyncEnumerable<string> SomeSortOfAwesomeness()
{
foreach (var line in File.ReadLines("Filename.txt"))
{
// simulates an async workload,
// otherwise why would be using IAsyncEnumerable?
// -- added due to popular demand
await Task.Delay(100);
yield return line;
}
}
或者
这只是一个打包的 APM 工作负载,请参阅Stephen Clearys的评论以进行澄清
public static async IAsyncEnumerable<string> SomeSortOfAwesomeness()
{
using StreamReader reader = File.OpenText("Filename.txt");
while(!reader.EndOfStream)
yield return await reader.ReadLineAsync();
}
用法
await foreach(var line in SomeSortOfAwesomeness())
{
Console.WriteLine(line);
}
斯蒂芬·克利里的更新
File.OpenText
遗憾的是只允许同步 I/O;在这种情况下,异步 API的实现很差。要打开真正的异步文件,您需要使用FileStream
构造函数传递isAsync
:true 或FileOptions.Asynchronous
.
ReadLineAsync
基本上会导致这段代码,如您所见,它只是 Stream APMBegin
和End
包装的方法
private Task<Int32> BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
{
return TaskFactory<Int32>.FromAsyncTrim(
this, new ReadWriteParameters { Buffer = buffer, Offset = offset, Count = count },
(stream, args, callback, state) => stream.BeginRead(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
(stream, asyncResult) => stream.EndRead(asyncResult)); // cached by compiler
}
推荐阅读
- firebase - 使用 Flutter 向 Cloud Firestore 添加对象
- angular - Angular CLI 升级重写了我的 angular-cli.json 设置
- r - R 币安 API 获取账户请求
- git - IntelliJ 中的本地更改,但针对整个功能分支
- scala - Scala - 一步计算两个变量
- vba - Excel VBA复制并粘贴到最后一行
- ruby-on-rails - 根据控制器中的 JSON API 响应 JSON
- hyperledger-fabric - 超级账本结构先前的哈希知道
- java - 无法在 Spring Boot 应用程序中设置 hystrix 仪表板
- nginx - 使用自定义日志格式时,nginx 变量为空