我搞不懂为什么下面的代码在调用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类中时,它似乎工作得很好。
发布于 2012-05-29 16:49:07
问题是您没有启动代理。您可以在创建代理后调用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()。每次访问属性时都会对其进行重新计算,因此您的代码会执行相同的操作,但最佳实践不建议使用执行复杂工作的属性。
发布于 2012-05-29 16:49:21
您忘记启动邮箱:
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() |> ignorehttps://stackoverflow.com/questions/10795648
复制相似问题