首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的MailboxProcessor挂了?

为什么我的MailboxProcessor挂了?
EN

Stack Overflow用户
提问于 2012-05-29 16:33:24
回答 2查看 352关注 0票数 3

我搞不懂为什么下面的代码在调用GetTotal时挂起。我似乎不能在MailboxProcessor中进行调试,所以很难看出发生了什么。

代码语言:javascript
运行
复制
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类中时,它似乎工作得很好。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-05-29 16:49:07

问题是您没有启动代理。您可以在创建代理后调用Start

代码语言:javascript
运行
复制
let myAgent = (...)
do myAgent.Start()

或者,您可以使用MailboxProcessor<'T>.Start创建代理,而不是调用构造函数(我通常更喜欢这种方法,因为它看起来更实用):

代码语言:javascript
运行
复制
let myAgent = MailboxProcessor<Message<'T, 'TState>>.Start(fun inbox ->  (...) )

我认为您无法调试代理,因为代理内部的代码并未实际运行。我尝试在调用代理内部的Receive之后立即添加printfn "Msg: %A" message (以打印传入的消息以进行调试),并且我注意到,在调用Aggregate之后,代理实际上没有收到任何消息……(只有在调用GetTotal之后才会被阻止,这将保存回复)

顺便说一句,我可能会将GetTotal转换为一个方法,因此您应该调用GetTotal()。每次访问属性时都会对其进行重新计算,因此您的代码会执行相同的操作,但最佳实践不建议使用执行复杂工作的属性。

票数 7
EN

Stack Overflow用户

发布于 2012-05-29 16:49:21

您忘记启动邮箱:

代码语言:javascript
运行
复制
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
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10795648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档