Rough! Creo que esto es imposible, porque reubicar corresponde a una instrucción especial IL que capta la excepción desde la parte superior de la pila, pero la forma en que las expresiones asincrónicas se compilan en una cadena de continuaciones, ¡no creo que la semántica se mantenga!
Por la misma razón, la siguiente no se compilará bien:
try
(null:string).ToString()
with e ->
(fun() -> reraise())()
En estas situaciones, en las que necesito para manejar la excepción fuera de la with
corporal real, y que le gustaría emular reraise
(que es, preservar el seguimiento de la pila de la excepción), utilizo solución this, por lo que todos juntos el código se vería así:
let inline reraisePreserveStackTrace (e:Exception) =
let remoteStackTraceString = typeof<exn>.GetField("_remoteStackTraceString", BindingFlags.Instance ||| BindingFlags.NonPublic);
remoteStackTraceString.SetValue(e, e.StackTrace + Environment.NewLine);
raise e
let executeAsync context = async {
traceContext.Properties.Add("CorrelationId", context.CorrelationId)
try
do! runAsync context
return None
with
| e when isCriticalException(e) ->
logCriticalException e
reraisePreserveStackTrace e
| e ->
logException e
return Some(e)
}
actualización: .NET 4. 5 introducido ExceptionDispatchInfo que puede permitir una implementación más limpia de reraisePreserveStackTrace
anterior.
Esta respuesta es quizás obsoleta. En .NET 4.5 puede usar la clase 'ExceptionDispatchInfo', que hace esto y también captura la información del cubo de Watson, como el ensamblado de origen y el desplazamiento IL. http://msdn.microsoft.com/en-us/library/system.runtime.exceptionservices.exceptiondispatchinfo(v=vs.110).aspx –
@DaxFohl podría proporcionar una respuesta actualizada utilizando 'ExceptionDispatchInfo'? –