假设我们具有以下C#方法
public async Task DoStuffAsync(string path)
{
var fullPath = Path.Combine(
Directory.GetCurrentDirectory(),
path
);
using var stream = File.OpenText(fullPath);
while (!stream.EndOfStream)
{
var line = await stream.ReadLineAsync();
await Console.Out.WriteLineAsync(line);
}
}
我们想在F#中实现它,我的第一个尝试就是这样编写代码
let doStuffAsync path =
async {
let fullPath = Path.Combine(Directory.GetCurrentDirectory(), path)
use stream = File.OpenText fullPath
while (not stream.EndOfStream) do
let! line = stream.ReadLineAsync() |> Async.AwaitTask
System.Console.Out.WriteLineAsync(line) |> Async.AwaitTask |> ignore
}
但是这对我来说不是正确的,因为我们必须将Task<string>
解压缩为Async<string>
,然后再解压缩。与Task
中的WriteLineAsync
相同。
方法ReadLineAsync
和WriteLineAsync
的F#变体是否返回Async<_>
而不是Task<_>
?
还有某种异步管道操作员可以让我做
stream.ReadLineAsync()
|> Async.AwaitTask
|> System.Console.Out.WriteLineAsync
|> Async.AwaitTask
|> ignore
答案 0 :(得分:1)
正如@NghiaBui所指出的,使用Async.AwaitTask
是正确的。这是两个异步模型,您需要在它们之间进行转换。
恐怕Async<'T>
和大多数.net核心库都没有ReadlineAsync
变体。
您可以使用TaskBuilder来使用一些更简洁的语法:
task {
let fullPath = Path.Combine(Directory.GetCurrentDirectory(), path)
use stream = File.OpenText fullPath
while (not stream.EndOfStream) do
let! line = stream.ReadLineAsync()
do! System.Console.Out.WriteLineAsync line
}
关于管道,恐怕是不可能的。有一些discussions可以引入|>!
运算符,但看起来它会增加不必要的复杂性。