KCT*_*KCT 5 f# asynchronous let async-workflow
我正在尝试理解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)
Run Code Online (Sandbox Code Playgroud)
我定义了一个异步工作流,其中TryOpenAsync返回一个Task类型.我用Async.AwaitTask将它转换为Async.(副任务:"等待"任务?它不等待它只是转换它,是吗?我认为它与Task.Wait或await关键字无关).让我"等待"它!并返回它.要启动工作流,我使用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)
Run Code Online (Sandbox Code Playgroud)
我认为AwaitTask使它成为Async和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)
Run Code Online (Sandbox Code Playgroud)
我只是将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
Run Code Online (Sandbox Code Playgroud)
FSI中无法运行代码的结果:
>
Run Code Online (Sandbox Code Playgroud)
你不能再在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
第二个代码块看起来应该对我有用。Stream如果我为和提供虚拟实现,它确实会运行它StreamOpenResult。
您应该尽可能避免使用,Async.RunSynchronously因为它违背了异步的目的。将所有这些代码放在一个更大的async块中,然后您将可以访问StreamOpenResult:
async {
let! openResult = Stream.TryOpenAsync(partition) |> Async.AwaitTask
let stream = if openResult.Found then openResult.Stream else Stream(partition)
return () // now do something with the stream
}
Run Code Online (Sandbox Code Playgroud)
您可能需要在程序的最外边缘放置一个Async.Startor才能实际运行它,但如果您有(或将其转换为 a )并将其传递给可以调用的其他代码(例如 Web 框架),那就更好了它以非阻塞的方式。Async.RunSynchronouslyasyncTask