奇怪的事情...我只是想对 F# 中的异常做一个简单的重试,但捕获没有捕获 :) 有什么想法吗?
let rec retry times next event =
async {
try
return! next event
with
| _ when times > 0 -> return! retry (times - 1) next event
| error -> return error.Reraise()
}
如果 next 是一个函数,如;
let handler evt = async { failwith "Oh-no" }
然后 try 中的代码执行但没有被捕获。到底是怎么回事? :O
再加注是一种扩展方法,如下所述:https://github.com/fsharp/fslang-suggestions/issues/660 by nikonthethird。
type Exception with
member this.Reraise () =
(ExceptionDispatchInfo.Capture this).Throw ()
Unchecked.defaultof<_>
答案 0 :(得分:1)
您的代码确实捕获了异常。这是我正在运行以测试它的完整程序:
let rec retry times next event =
async {
try
printfn "Retry: %A" times
return! next event
with
| _ when times > 0 -> return! retry (times - 1) next event
| error -> raise error
}
let handler evt =
async {
printfn "About to fail once"
failwith "Oh-no"
}
[<EntryPoint>]
let main argv =
retry 3 handler ()
|> Async.RunSynchronously
|> printfn "%A"
0
输出:
Retry: 3
About to fail once
Retry: 2
About to fail once
Retry: 1
About to fail once
Retry: 0
About to fail once
Unhandled exception. System.Exception: Oh-no
您可以看到异常正在被捕获,因为在 handler
放弃之前多次调用了 retry
。
注意事项:
return error.Reraise()
替换了 raise error
,因为 Exception.Reraise
不是定义的方法。我不确定您在这里有什么想法,但这不会直接影响您问题的答案。retry
(我使用 ()
作为“事件”)非常重要,然后同步运行生成的 async
计算。也许你没有这样做?Async.Catch
来处理异步异常。