Грубые!Я думаю, что это невозможно, потому что reraise соответствует специальной инструкции IL, которая захватывает исключение из верхней части стека, но то, как асинхронные выражения компилируются в цепочку продолжений, я не думаю, что семантика верна!
По той же причине следующее не будет компилироваться:
try
(null:string).ToString()
with e ->
(fun () -> reraise())()
В этих ситуациях, когда мне нужно обработать исключение за пределами фактического with
тела, и я хотел бы эмулироватьreraise
(то есть сохранить трассировку стека исключения), я использую это решение, поэтому весь ваш код будет выглядеть так:
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)
}
Обновление: .NET 4.5 представил ExceptionDispatchInfo , что может позволить более чистую реализацию reraisePreserveStackTrace
выше.