簡體   English   中英

為什么我的郵箱處理器掛起了?

[英]Why is my MailboxProcessor hanging?

我無法弄清楚為什么下面的代碼掛起來調用GetTotal 我似乎無法在MailboxProcessor內部進行調試,因此很難看到發生了什么。

module Aggregator

open System

type Message<'T, 'TState> =
    | Aggregate of 'T
    | GetTotal of AsyncReplyChannel<'TState>

type Aggregator<'T, 'TState>(initialState, f) =
    let myAgent = new MailboxProcessor<Message<'T, 'TState>>(fun inbox ->
        let rec loop agg =
            async {
                let! message = inbox.Receive()
                match message with
                    | Aggregate x -> return! loop (f agg x)
                    | GetTotal replyChannel ->
                        replyChannel.Reply(agg)
                        return! loop agg
            }
        loop initialState
        )

    member m.Aggregate x = myAgent.Post(Aggregate(x))
    member m.GetTotal = myAgent.PostAndReply(fun replyChannel -> GetTotal(replyChannel))

let myAggregator = new Aggregator<int, int>(0, (+))

myAggregator.Aggregate(3)
myAggregator.Aggregate(4)
myAggregator.Aggregate(5)

let totalSoFar = myAggregator.GetTotal
printfn "%d" totalSoFar

Console.ReadLine() |> ignore

它直接使用相同的MailboxProcessor似乎工作正常,而不是包裝在Aggregator類中。

問題是你沒有啟動代理。 您可以在創建代理后調用Start

let myAgent = (...)
do myAgent.Start()

或者,您可以使用MailboxProcessor<'T>.Start創建代理,而不是調用構造函數(我通常更喜歡這個選項,因為它看起來更實用):

let myAgent = MailboxProcessor<Message<'T, 'TState>>.Start(fun inbox ->  (...) )

我想您無法調試代理,因為代理內部的代碼實際上並未運行。 我嘗試在代理中調用Receive之后立即添加printfn "Msg: %A" message (打印傳入的消息以進行調試),我注意到,在調用Aggregate ,代理實際上沒有收到任何消息......(它只有在調用GetTotal后才會被阻止,這會回復

作為旁注,我可能會將GetTotal變成一個方法,所以你要調用GetTotal() 每次訪問屬性時都會重新評估屬性,因此您的代碼執行相同的操作,但最佳做法不建議使用執行復雜工作的屬性。

你忘了啟動郵箱:

open System

type Message<'T, 'TState> =
    | Aggregate of 'T
    | GetTotal of AsyncReplyChannel<'TState>

type Aggregator<'T, 'TState>(initialState, f) =
    let myAgent = new MailboxProcessor<Message<'T, 'TState>>(fun inbox ->
        let rec loop agg =
            async {
                let! message = inbox.Receive()
                match message with
                    | Aggregate x -> return! loop (f agg x)
                    | GetTotal replyChannel ->
                        replyChannel.Reply(agg)
                        return! loop agg
            }
        loop initialState
        )

    member m.Aggregate x = myAgent.Post(Aggregate(x))
    member m.GetTotal = myAgent.PostAndReply(fun replyChannel -> GetTotal(replyChannel))
    member m.Start() = myAgent.Start()

let myAggregator = new Aggregator<int, int>(0, (+))

myAggregator.Start()

myAggregator.Aggregate(3)
myAggregator.Aggregate(4)
myAggregator.Aggregate(5)

let totalSoFar = myAggregator.GetTotal
printfn "%d" totalSoFar

Console.ReadLine() |> ignore

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM