问题
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