Duplicate of: In C#, how can I rethrow InnerException without losing stack trace?
I have some operations that I invoke asynchronously on a background thread. Sometimes,
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
}
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 ;
}
You can't do that. throw
always resets the stack trace, unless used without parameter. I'm afraid your callers will have to use the InnerException...
Using the "throw" keyword with an exception will always reset the stack trace.
The best thing to do is to catch the actual exception you want, and use "throw;" instead of "throw ex;". Or to throw your own exception, with the InnerException that you want to pass along.
I don't believe what you want to do is possible.
As others have said, use the "throw" keyword without adding to it to keep the exception chain intact. If you need that original exception (assuming that is what you mean) then you could call Exception.GetBaseException() at the end of your chain to get the Exception that started it all.
No, that isn't possible. Your only real opportunity is to follow the recommended pattern and throw your own exception with the appropriate InnerException
.
Edit
If your concern is the presence of the TargetInvocationException
and you want to disregard it (not that I recommend this, as it could very well have something to do with the fact that it's being run on another thread) then nothing is stopping you from throwing your own exception here and attaching the InnerException
from the TargetInvocationException
as your own InnerException
. It's a little smelly, but it might accomplish what you want.
Although you may feel that the TargetInvocationException is "useless", it's the reality. Don't try to pretend that .NET didn't take the original exception and wrap it with a TargetInvocationException and throw it. That really happened. Some day, you might even want some piece of information that comes from that wrapping - like maybe the location of the code that threw the TargetInvocationException.