问题
My question is really simple. Please take a look at screenshot:
How could that happen? I explicitly put call to Async.RunSyncronously into try ... with.
回答1:
try/with in F# async workflows do not map directly to CLR protected blocks - instead if exception is raised in user code, library code will catch it and re-route to the nearest error continuation (which can be i.e with block, finally block, custom error continuation supplied in Async.StartWithContinuations etc...). This has a consequence that debugger might report about unhandled exceptions in user code that can be handled and processed later.
Snippet below reports the similar error in debugger but nevertheless execution is finished successfully
let error (): int = raise (System.TimeoutException())
let run() = async {
try
let result = error()
return result
with
:? System.TimeoutException -> return -1
}
let r = Async.RunSynchronously (run())
printfn "%d" r
回答2:
Try this:
let withTimeout (timeOut: option<int>) (operation: Async<'x>) : Async<option<'x>> =
match timeOut with
| None -> async {
let! result = operation
return Some result
}
| Some timeOut -> async {
let! child = Async.StartChild (operation, timeOut)
try
let! result = child
return Some result
with :? System.TimeoutException ->
return None
}
You should not use Async.RunSynchronously within async blocks, because doing so makes for suboptimal use of native threads and can lead to stack overflows. Async.RunSynchronously is for running Async computations from outside of such computations. Within an async block you can use plain let! and do! or, for example, Async.StartChild to run Async computations. This makes for more effective use of native threads and does not suffer from similar issues with potential stack overflows.
来源:https://stackoverflow.com/questions/26229949/f-cant-catch-timeoutexception