17

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メソッドを使用すると、この状況はさらに悪化します。結果としてデッドロックが保証されます。

そのような行動の理由はありますか?

4

2 に答える 2

15

ErrorMailboxProcessor にイベントがあります。

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

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

もちろん、自分で細かく制御したい場合は、Tomas のソリューションのようなこともできます。

于 2012-05-29T20:24:25.203 に答える
5

F# に例外を処理するためのメカニズムが含まれていない理由MailboxProcessorは、それを行うための最善の方法が明確でないためだと思います。たとえば、未処理の例外が発生したときにトリガーされるグローバル イベントが必要な場合がありますが、Postまたはへの次の呼び出しで例外を再スローする必要がある場合がありますPostAndReply

どちらのオプションも標準に基づいて実装できる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) 
于 2012-05-29T19:58:01.880 に答える