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