如何在保持堆栈跟踪到目前为止生成内部异常的同时呢? [英] How can I rethrow an Inner Exception while maintaining the stack trace generated so far?

查看:97
本文介绍了如何在保持堆栈跟踪到目前为止生成内部异常的同时呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

重复的:在C#中,如何我可以重新抛出InnerException,而不会丢失堆栈跟踪?

我有一些我在后台线程上异步调用的操作。有时,事情变坏当这种情况发生时,我倾向于获得一个TargetInvocationException,而在适当的时候它是没有用的。我真正需要的是TargetInvocationException的InnerException,如下所示:

I have some operations that I invoke asynchronously on a background thread. Sometimes, things go bad. When this happens, I tend to get a TargetInvocationException, which, while appropriate, is quite useless. What I really need is the TargetInvocationException's InnerException, like this:

    try
    {
        ReturnValue = myFunctionCall.Invoke(Target, Parameters);
    }
    catch (TargetInvocationException err)
    {
        throw err.InnerException;
    }

这样一来,我的来电者就发生了REAL异常。问题是,throw语句似乎重置堆栈跟踪。我想基本上重新抛出内部异常,但是保持原来的堆栈跟踪。如何做到这一点?

That way, my callers are served up with the REAL exception that occured. The problem is, that the throw statement seems to reset the stack trace. I'd like to basically rethrow the inner exception, but keep the stack trace it originally had. How do I do that?

澄清:
我只想要内部异常的原因是这个类试图'抽象所有这些功能(由调用者提供的委托)都在其他线程上运行,而且没有任何事情。如果有异常,那么与后台线程运行无关,调用者真的喜欢进入代理的堆栈跟踪,找到真正的问题,而不是调用调用。 p>

CLARIFICATION: The reason I want only the inner exception is that this class tries to 'abstract away' the whole fact that these functions (delegates supplied by caller) are run on other threads and whatnot. If there is an exception, then odds are it has nothing to do with being run on a background thread, and the caller would really like the stack trace that goes into their delegate and finds the real issue, not my call to invoke.

推荐答案

可以在重新抛出之前保留堆栈跟踪:

It is possible to preserve the stack trace before rethrowing without reflection:

static void PreserveStackTrace (Exception e)
{
    var ctx = new StreamingContext  (StreamingContextStates.CrossAppDomain) ;
    var mgr = new ObjectManager     (null, ctx) ;
    var si  = new SerializationInfo (e.GetType (), new FormatterConverter ()) ;

    e.GetObjectData    (si, ctx)  ;
    mgr.RegisterObject (e, 1, si) ; // prepare for SetObjectData
    mgr.DoFixups       ()         ; // ObjectManager calls SetObjectData

    // voila, e is unmodified save for _remoteStackTraceString
}

与InternalPreserveStackTrace相比,这浪费了很多周期,但具有依赖于公共功能的优势。以下是堆栈跟踪保留功能的常见使用模式:

This wastes a lot of cycles compared to InternalPreserveStackTrace, but has the advantage of relying only on public functionality. Here are a couple of common usage patterns for stack-trace preserving functions:

// usage (A): cross-thread invoke, messaging, custom task schedulers etc.
catch (Exception e)
{
    PreserveStackTrace (e) ;

    // store exception to be re-thrown later,
    // possibly in a different thread
    operationResult.Exception = e ;
}

// usage (B): after calling MethodInfo.Invoke() and the like
catch (TargetInvocationException tiex)
{
    PreserveStackTrace (tiex.InnerException) ;

    // unwrap TargetInvocationException, so that typed catch clauses 
    // in library/3rd-party code can work correctly;
    // new stack trace is appended to existing one
    throw tiex.InnerException ;
}

这篇关于如何在保持堆栈跟踪到目前为止生成内部异常的同时呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆