I needed to reraise an exception that occurs while executing an async block, after logging the exception.
When I do the following the compiler thinks that I am not calling the reraise function from within the handler. What am I doing wrong?
let executeAsync context = async {
traceContext.Properties.Add("CorrelationId", context.CorrelationId)
try
do! runAsync context
return None
with
| e when isCriticalException(e) ->
logCriticalException e
reraise()
| e ->
logException e
return Some(e)
}
Rough! I think this is impossible, because reraise corresponds to a special IL instruction that grabs the exception from the top of the stack, but the way async expressions are compiled into a chain of continuations, I don’t think the semantics hold!
For the same reason, the following won’t compile either:
In these situations, where I need to handle the exception outside of the actual
withbody, and would like to emulatereraise(that is, preserve the stack trace of the exception), I use this solution, so all together your code would look like:Update: .NET 4.5 introduced ExceptionDispatchInfo which may allow a cleaner implementation of
reraisePreserveStackTraceabove.