具有多个递归异步正文的 F# 代理是否可以使用多个收件箱.接收() 在每个



我这里有一个多状态 F# 邮箱处理器示例,只是想知道为什么它会编译但行为出乎意料 - F# 代理只能有一个收件箱吗?在传入的 lambda 函数中接收(( 语句?我正在尝试遵循"Expert F# 3.0"第 284 页中提供的常规示例模式,其中使用多个异步 {} 正文允许多种状态,但并不具体说明收件箱是否。Receive(( 可以在每个异步中使用吗?

open System
let mb1<'T> = MailboxProcessor<string>.Start(fun inbox ->
                        let rec loop1 (n:int) = async {
                                    printfn "loop1 entry "
                                    let! msg = inbox.Receive()
                                    do! Async.Sleep(1000)
                                    printfn "loop1 calling loop2"  //msg received %A" msg
                                    return! loop2 (n+1) }
                        and loop2 (x:int) =     async {
                                    printfn "loop2 entry"
                                    let! msg2 = inbox.Receive()
                                    printfn "loop2 msg received %A" msg2
                                    printfn "loop2 calling loop1"
                                    return! loop1 (x+1) }
        loop2 0                    
                                        )
mb1.Post("data message 1")
mb1.Post("data message 2")

收益 率

loop2 entry
loop2 msg received "data message 1"
loop2 calling loop1
loop1 entry 
val it : unit = ()
> 
loop2 entry
loop2 msg received "data message 2"
loop2 calling loop1
loop1 entry 
val it : unit = ()
> 

所以让! 味精 = 收件箱。循环 1 中的 receive(( 被跳过了?我本以为 loop2 在返回时已经完成!循环1和那个让!收件箱的分配。Receive(( 特定于它使用的异步块。

这与所谓的"值限制"有关。

由于您为mb1提供了显式泛型参数,因此它被编译为函数,而不是值。在不涉及太多细节的情况下,编译器必须这样做,以便于使用不同的泛型参数访问值的可能性。

因此,每次"引用"mb1时,实际发生的是一个创建全新代理的函数调用,因此两个.Post调用发生在不同的对象上。

要纠正这种情况,请从值中删除泛型参数,从而使其成为真正的计算一次值:

let mb1 = MailboxProcessor<string>( ...

或者确保只调用一次:

let mb = mb1
mb.Post("data message 1")
mb.Post("data message 2")

相关内容

  • 没有找到相关文章

最新更新