[英]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.