gpt4 book ai didi

asynchronous - 为什么 Async.StartChild 返回 `Async>`?

转载 作者:行者123 更新时间:2023-12-05 03:41:29 26 4
gpt4 key购买 nike

我是 F# 的新手,我一直在阅读 F# for Fun and Profit。在为什么使用 F#? 系列中,有一个 post描述异步代码。我遇到了 Async.StartChild函数,我不明白为什么返回值是这样。

例子:

let sleepWorkflow  = async {
printfn "Starting sleep workflow at %O" DateTime.Now.TimeOfDay
do! Async.Sleep 2000
printfn "Finished sleep workflow at %O" DateTime.Now.TimeOfDay
}

let nestedWorkflow = async {

printfn "Starting parent"
let! childWorkflow = Async.StartChild sleepWorkflow

// give the child a chance and then keep working
do! Async.Sleep 100
printfn "Doing something useful while waiting "

// block on the child
let! result = childWorkflow

// done
printfn "Finished parent"
}

我的问题是为什么不应该 Async.StartChild只需返回 Async<'T>而不是 Async<Async<'T>> ?你必须使用 let!两次。 documentation甚至说:

This method should normally be used as the immediate right-hand-side of a let! binding in an F# asynchronous workflow [...] When used in this way, each use of StartChild starts an instance of childComputation and returns a completor object representing a computation to wait for the completion of the operation. When executed, the completor awaits the completion of childComputation.

在一些测试中,添加了一些对 sleep 的调用,似乎没有初始的let!子计算从未开始。

为什么会有这种返回类型/行为?我习惯在 C# 中调用 async方法将始终立即“启动”任务,即使您不这样做也是如此 await它。事实上,在 C# 中,如果 async方法不调用任何异步代码,它将同步运行。

编辑澄清:

这样做有什么好处:

let! waiter = Async.StartChild otherComp // Start computation
// ...
let! result = waiter // Block

与 if Async.StartChild 相比返回了 Async<'T> :

let waiter = Async.StartChild otherComp // Start computation
// ...
let !result = waiter // Block

最佳答案

想法是这样的:你用 let wait = Async.StartChild otherComp 开始另一个异步计算(在后台)然后你让服务员回来。

这意味着 let! result = waiter阻塞并随时等待后台计算的结果。

如果Async.StartChild会返回 Async<'t>你会等待 let! x = otherComp就在那里,它就像一个正常让!结果 = 其他补偿`


是的,F# Async-Workflows 只会在您执行类似 Async.Start... 的操作后启动Async.RunSynchronously (它不像 Task,通常在您创建它后立即运行)

这就是为什么在 C# 中您可以一次创建一个任务 ( var task = CreateMyTask() )(即 Async.StartChild 部分)然后稍后使用 var result = await task在那里等待结果(即 let! result = waiter 部分)。


为什么 Async.StartChild返回 Async<Async<'T>>而不是 Async<'T>

这是因为以这种方式启动的工作流应该表现得像一个-task/process。当您取消包含的工作流时,也应该被取消

因此,在技术层面上,子工作流需要访问取消 token 而无需您明确传递它,这是 Async 的一回事- 使用 Bind 时在后台为您键入句柄(在这里又名 let!)。

所以它必须是这种类型才能使取消 token 的传递起作用。

关于asynchronous - 为什么 Async.StartChild 返回 `Async<Async<' T>>`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67723546/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com