7

Doing this is bad form because it doesn't preserve a stack trace:

try { /*... some code that can throw an exception ...*/ }
catch (Exception e)
{
    throw e; // ...Use "throw;" by itself instead
}

However, if the exception is caught on a non-UI thread, I want to do raise it back up to the UI and handle it so the user gets the message like so:

try { /*... some code that can throw an exception ...*/ }
catch (Exception e)
{
    Dispatcher.Invoke((Action)(() => { throw; }));
}

However, I can't use the throw keyword by itself here because the C# lexer (correctly) doesn't think the throw statement is inside of a catch. I have to instead do:

try { /*... some code that can throw an exception ...*/ }
catch (Exception e)
{
    Dispatcher.Invoke((Action)(() => { throw e; }));
}

and re-throw the exception, which loses its stack trace.

Is there any (easy) way to get around this (I could always package the stack trace at the time the exception is ready to switch threads, but that seems hokey)?

Note: I saw this thread but it's similar in title only, not content.

Community
  • 1
  • 1
Michael
  • 3,099
  • 4
  • 31
  • 40
  • 1
    Have you tried throwing a new `Exception` using the `Exception, string, Exception` constructor? That way your inner exception would be the original exception. – Daniel Kelley Feb 01 '13 at 19:56
  • Any reaaon why you try/catch it in the first place, when all you do is re-throw it. Also, Stack Trace will folliw if you put thw PDB files wil the EXE/DLLs. – Mats Magnem Feb 01 '13 at 19:57
  • duplicate? http://stackoverflow.com/questions/57383/in-c-how-can-i-rethrow-innerexception-without-losing-stack-trace?rq=1 – vidstige Feb 01 '13 at 19:58
  • in a separate note, i recommend exiting the catch-block and then invoke. You'll get flow paths that are easier to understand if for example a new exception is thrown inside the invokded action. – vidstige Feb 01 '13 at 19:59

1 Answers1

4

The usual way to do this is to throw a new exception, with the original included as InnerException. Exception has a special constructor for this.

But if you really want to do this and you're on .Net 4.5, you can use ExceptionDispatchInfo to capture the stack trace of the exception and then rethrowing it somewhere else without resetting the stack trace. But in most situations, using the old method of wrapping the exception in a new one is probably better.

svick
  • 236,525
  • 50
  • 385
  • 514