我试图理解 F# 中的异步工作流,但我发现了一个我真的不明白的部分。
以下代码工作正常:
let asynWorkflow = async{
let! result = Stream.TryOpenAsync(partition) |> Async.AwaitTask
return result
}
let stream = Async.RunSynchronously asynWorkflow
|> fun openResult -> if openResult.Found then openResult.Stream else Stream(partition)
我定义了一个异步工作流,其中 TryOpenAsync 返回一个Task<StreamOpenResult>
类型。我将其转换为Async<StreamOpenResult>
Async.AwaitTask。(支线任务:“等待”任务?它不等待它只是转换它,是吗?我认为它与 Task.Wait 或 await 关键字无关)。我“等待”它let!
并返回它。要启动工作流,我使用 RunSynchronously 应该启动工作流并返回结果(绑定它)。根据结果,我检查是否找到了流。
但现在我的第一个问题。为什么我必须将 TryOpenAsync 调用包装在另一个异步计算中并让!(“等待”)呢?例如以下代码不起作用:
let asynWorkflow = Stream.TryOpenAsync(partition) |> Async.AwaitTask
let stream = Async.RunSynchronously asynWorkflow
|> fun openResult -> if openResult.Found then openResult.Stream else Stream(partition)
我认为 AwaitTask 使它成为Async<T>
并且RunSynchronously
应该启动它。然后使用结果。我想念什么?
我的第二个问题是为什么有任何“Async.Let!” 功能可用?也许是因为它不起作用或更好,为什么它不能与以下代码一起使用?
let ``let!`` task = async{
let! result = task |> Async.AwaitTask
return result
}
let stream = Async.RunSynchronously ( ``let!`` (Stream.TryOpenAsync(partition)) )
|> fun openResult -> if openResult.Found then openResult.Stream else Stream(partition)
我只是将 TryOpenAsync 作为参数插入,但它不起作用。通过说不起作用,我的意思是整个 FSI 都会挂起。所以它与我的异步/“等待”有关。
- - 更新:
FSI 中的工作代码结果:
>
Real: 00:00:00.051, CPU: 00:00:00.031, GC gen0: 0, gen1: 0, gen2: 0
val asynWorkflow : Async<StreamOpenResult>
val stream : Stream
FSI 中代码无效的结果:
>
而且您不能再在 FSI 中执行任何操作
--- 更新 2
我正在使用 Streamstone。这里是 C# 示例:https ://github.com/yevhen/Streamstone/blob/master/Source/Example/Scenarios/S04_Write_to_stream.cs
这里是 Stream.TryOpenAsync:https ://github.com/yevhen/Streamstone/blob/master/Source/Streamstone/Stream.Api.cs#L192