我正在尝试通过该类开始使用 F# 中的代理,但MailboxProcessor<'Msg>
我很快意识到我没有对异常进行适当的处理。在 Haskellian 世界中,不会有任何例外,因此处理问题的正确方法是简单地将它们作为响应案例提供;因此代理可以回复如下内容:
type AgentResponse =
| HandledData of string
| InvalidData of string
然后可以调用代理的.PostAndReply
方法并获得InvalidData
包含指示数据无效原因的消息。但是,这不是 Haskell,有时会发生异常。所以如果我这样做:
let agent =
new MailboxProcessor<string * AsyncReplyChannel<AgentResponse>>(fun inbox ->
async {
while true do
let! (msg, replyChannel) = inbox.Receive()
if msg = "die" then failwith "Unknown exception encountered!"
else replyChannel.Reply(HandledData(msg))
})
agent.Start()
agent.PostAndReply (fun rc -> "die", rc)
agent.PostAndReply (fun rc -> "Test", rc)
第二次调用agent.PostAndReply
无限期阻塞。当不使用AsyncReplyChannel
并因此只是调用agent.Post
时,调用不会阻塞,但是一旦代理遇到异常,新消息就会留在队列中。在任何一种情况下重新启动代理似乎都是不可能的,因为该agent.Start
函数InvalidOperationException
在再次调用时返回一个,处理这个问题的自然方法似乎是创建一个具有干净状态的新代理,但随后所有排队的消息都丢失了。
除了将代理的整个主体包装在 中之外try..with
,还有什么好方法可以让代理在异常后继续运行?或者,是否已经建立了一种“标准”的处理方式,有人可以指出我?