粗糙!我认为这是不可能的,因为重新生成对应于一个特殊的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'提供更新的答案? –