F# 异步尝试不捕获异常
F# async try with not catching exceptions
奇怪的事情...我只是想在 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()
}
如果下一个是这样的函数;
let handler evt = async { failwith "Oh-no" }
然后执行try中的代码但没有被捕获。到底是怎么回事? :O
更新
reraise 是一种扩展方法,如下所述:https://github.com/fsharp/fslang-suggestions/issues/660 by nikontethird。
type Exception with
member this.Reraise () =
(ExceptionDispatchInfo.Capture this).Throw ()
Unchecked.defaultof<_>
您的代码确实捕获了异常。这是我正在 运行 测试的完整程序:
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
放弃之前被多次调用。
备注:
- 我用
raise error
替换了 return error.Reraise()
,因为 Exception.Reraise
不是定义的方法。我不确定你在这里想到的是什么,但这并不直接影响你问题的答案。
- 使用所有三个参数完全调用
retry
很重要(我使用 ()
作为“事件”),然后 运行 同步计算结果 async
.也许你没有那样做?
- 您可能想考虑使用
Async.Catch
来处理异步异常。
奇怪的事情...我只是想在 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()
}
如果下一个是这样的函数;
let handler evt = async { failwith "Oh-no" }
然后执行try中的代码但没有被捕获。到底是怎么回事? :O
更新
reraise 是一种扩展方法,如下所述:https://github.com/fsharp/fslang-suggestions/issues/660 by nikontethird。
type Exception with
member this.Reraise () =
(ExceptionDispatchInfo.Capture this).Throw ()
Unchecked.defaultof<_>
您的代码确实捕获了异常。这是我正在 运行 测试的完整程序:
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
放弃之前被多次调用。
备注:
- 我用
raise error
替换了return error.Reraise()
,因为Exception.Reraise
不是定义的方法。我不确定你在这里想到的是什么,但这并不直接影响你问题的答案。 - 使用所有三个参数完全调用
retry
很重要(我使用()
作为“事件”),然后 运行 同步计算结果async
.也许你没有那样做? - 您可能想考虑使用
Async.Catch
来处理异步异常。