qeh*_*hgt 15 f# mailboxprocessor
我想知道,为什么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
Run Code Online (Sandbox Code Playgroud)
没有任何反应.程序执行没有致命的停止,或者出现带有"未处理的异常"的消息框.没有.
如果有人使用PostAndReply方法,这种情况会变得更糟:结果是保证死锁.
这种行为有什么理由吗?
Bri*_*ian 13
ErrorMailboxProcessor上有一个事件.
http://msdn.microsoft.com/en-us/library/ee340481
counter.Error.Add(fun e -> printfn "%A" e)
Run Code Online (Sandbox Code Playgroud)
当然,如果你想自己施加精细控制,你可以做一些类似Tomas的解决方案.
我认为MailboxProcessorF#中不包含任何处理异常的机制的原因是不清楚这样做的最佳方法是什么.例如,您可能希望在发生未处理的异常时触发全局事件,但您可能希望在下次调用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
Run Code Online (Sandbox Code Playgroud)
要使用它,您将编写与之前编写的代码相同的代码,但您现在可以异步处理异常:
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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1269 次 |
| 最近记录: |