粗糙!我認爲這是不可能的,因爲重新生成對應於一個特殊的IL指令,它從棧頂捕獲異常,但是異步表達式被編譯成一個連續的鏈,我不認爲這個語義成立了!
出於同樣的原因,下面將無法編譯之一:
try
(null:string).ToString()
with e ->
(fun() -> reraise())()
在這種情況下,我需要處理實際with
體之外的例外,想效仿reraise
(即是,保持異常的堆棧跟蹤),我用this解決方案,讓所有一起您的代碼將是這樣的:
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
。
這個答案也許是過時的除外。在.net 4.5中,你可以使用'ExceptionDispatchInfo'類,它執行此操作,並捕獲Watson桶信息,如原點集和IL偏移量。 http://msdn.microsoft.com/en-us/library/system.runtime.exceptionservices.exceptiondispatchinfo(v=vs.110).aspx –
@DaxFohl可以使用'ExceptionDispatchInfo'提供更新的答案? –