繁体   English   中英

F# MailboxProcessor 异步混乱打印语句

[英]F# MailboxProcessor async messed print statements

我正在尝试制作一个正在处理订单的酒吧模拟器。 发送给代理的消息属于这种类型。

type DTGCafeMessage =
    | OrderDrink of Drink * float
    | LeaveAComment of string

代理是下面实现的一个吧class。

type Bar() =
    let dtgCafeAgent =
        MailboxProcessor.Start
            (fun inbox ->
                let rec messageLoop () =
                    async {
                        let! msg = inbox.Receive()

                        match msg with
                        | OrderDrink (drink, amount) ->
                            let drinkPrice : float = getPrice drink
                            let mutable totalPrice = ((drinkPrice: float) * (amount: float))

                            if drink.type' = Coffee then
                                totalPrice <- dgtVAT totalPrice VAT

                            printfn
                                "Please pay DKK%d for your %d %A %A drinks. %s!"
                                (Convert.ToInt32(totalPrice))
                                (Convert.ToInt32(amount))
                                (string drink.type')
                                (string drink.size)
                                "Thanks!"
                        | LeaveAComment (comment) -> printf "Comment: %A" comment

                        return! messageLoop ()
                    }

                messageLoop ())

    member this.Order msg = dtgCafeAgent.Post msg


当我将消息发送给代理时,它正在以非常混乱的方式打印内容。

let bar = Bar()
let testDrink = { type' = Coffee; size = Small }

bar.Order(OrderDrink({ type' = Coffee; size = Small }, 2.0))

let orderDrinks =
    [ (OrderDrink({ type' = Coffee; size = Small }, 1.0))
      (OrderDrink({ type' = Coffee; size = Medium }, 2.0))
      (OrderDrink({ type' = Juice; size = Small }, 3.0))
      (OrderDrink({ type' = Soda; size = Medium }, 4.0))
      (OrderDrink({ type' = Milk; size = Large }, 5.0)) ]

orderDrinks |> List.map (fun o -> bar.Order o)

// output
> orderDrinks |> List.map (fun o -> bar.Order o);;
valPlease pay DKK24 for your 1  "Coffee" "Small" drinks. Thanks!!
it Please pay DKK72 for your 2 "Coffee" :"Medium" drinks. Thanks!!
 unitPlease pay DKK 45 for your 3 list"Juice" "Small" drinks. Thanks!!
 =Please pay DKK51 for your 4  "Soda" "Medium" drinks. Thanks!!
[()Please pay DKK;125 for your 5 "Milk"  "Large" drinks. Thanks!!
(); (); (); ()]

如我所见,它应该打印代码中编写的每条语句。

Fsi 正在评估您的表情。 由于 bar.Order() 返回单位,因此表达式的结果是 [(); (); (); (); ()]。 所以 Fsi 想要打印类似的东西

val it : unit list = [(); (); (); (); ()]

同时,邮箱处理器在另一个线程上处理它的队列,同时打印消息。 两个线程都在向同一个 output 发送文本,即它们相互踩踏。

做就是了

orderDrinks |> List.iter bar.Order

如果您只想打印结果。

List.map 将改为转换 output,但 output 是单元类型,例如 () 并得到你看到的乱码结果。

编辑:您还需要启动 fsi quiet 所以它不会打印变量评估,例如 fsi --quiet

否则行为是正确的,因为它显示了邮箱处理器如何开始执行任务,并在完成之前将控制权移交给调用者。 因此调用者 fsi 开始打印 val it: unit ()。 同时邮箱处理器正在工作。 两个进程同时写入控制台,产生乱码 output。

当您执行没有 output 的函数时仍然使用 List.Iter,例如有单元 () output; 这反过来将只返回一个单位 () output 而不是每个列表项一个单位 ()。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM