MailboxProcessor和异常(MailboxProcessor and exception

2019-06-24 22:34发布

我想知道,为什么MailboxProcessor的处理异常的默认策略只是默默地忽略它们。 例如:

let counter =
    MailboxProcessor.Start(fun inbox ->
        let rec loop() =
            async { printfn "waiting for data..."
                    let! data = inbox.Receive()
                    failwith "fail" // simulate throwing of an exception
                    printfn "Got: %d" data
                    return! loop()
            }
        loop ())
()
counter.Post(42)
counter.Post(43)
counter.Post(44)
Async.Sleep 1000 |> Async.RunSynchronously

并没有任何反应。 还有就是程序的执行,或“未处理的异常”的提示框的无致命停止出现。 没有。

如果有人使用,这种情况变得更差PostAndReply保证僵局的结果是:方法。

任何原因的行为?

Answer 1:

我想,为什么的原因MailboxProcessor在F#中不包含异常处理的任何机制是目前尚不清楚什么是做的最好的方法。 例如,您可能希望当未处理的异常情况发生时触发一个全球性的事件,但你可能要重新抛出下一个呼叫异常PostPostAndReply

这两个选项可以基于标准执行MailboxProcessor ,所以它是可以添加你想要的行为。 例如,下面的代码片段显示HandlingMailbox ,增加了一个全球性的异常处理程序。 它具有相同的接口,正常MailboxProcessor (我省略了一些方法),但它增加OnError事件,当发生异常时触发:

type HandlingMailbox<'T> private(f:HandlingMailbox<'T> -> Async<unit>) as self =
  let event = Event<_>()
  let inbox = new MailboxProcessor<_>(fun inbox -> async {
    try 
      return! f self
    with e ->
      event.Trigger(e) })
  member x.OnError = event.Publish
  member x.Start() = inbox.Start()
  member x.Receive() = inbox.Receive()
  member x.Post(v:'T) = inbox.Post(v)
  static member Start(f) =
    let mbox = new HandlingMailbox<_>(f)
    mbox.Start()
    mbox

要使用它,你会写同样的代码,你写之前,但你现在可以异步处理异常:

let counter = HandlingMailbox<_>.Start(fun inbox -> async {
  while true do 
    printfn "waiting for data..." 
    let! data = inbox.Receive() 
    failwith "fail" })

counter.OnError.Add(printfn "Exception: %A")
counter.Post(42) 


Answer 2:

有一个Error在MailboxProcessor事件。

http://msdn.microsoft.com/en-us/library/ee340481

counter.Error.Add(fun e -> printfn "%A" e)

当然,如果你想自己发挥很好的控制,你可以这样做托马斯的解决方案。



文章来源: MailboxProcessor and exceptions