TargetInvocationException from BackgroundWorker_RunWorkerCompleted

3.8k views Asked by At

Suppose the following situation. A form has a button that on click starts a background worker. In RunWorkerCompleted event handler there is a piece of code that throws unhandeled exception. The form is started from Application.Run method.

public partial class FormMain : Form
{
    public FormMain()
    {
        InitializeComponent();
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        throw new Exception();
    }

    private void button_Click(object sender, EventArgs e)
    {
        backgroundWorker.RunWorkerAsync();
    }
}

The problem is that Visual Studio breaks at Application.Run call instead at "throw new Exception()" in FormMain.backgroundWorker_RunWorkerCompleted method. On top of that real exception is wrapped with TargetInvocationException and call stack is reduced to Program.Main method and code that caused exception can't be inspected because of that.

How to prevent that wrapping? Am I doing something intrinsically wrong?

Judging from the call stack supplied with TargetInvocationException, there are a lot of invocation methods stacked up, too much for my basic understanding of message loops and not-so-basic understanding of threading.

EDIT: I know there is InnerException property in TargetInvocationException and that the error can be traced by looking there but that is not the question. The question is how to make Visal Studio stop before wrapping real exception with TargetInvocationException so I can use all those nice debugging features that VS IDE provides.

1

There are 1 answers

4
Hans Passant On BEST ANSWER

Yes, this is an unfortunate side effect from the magic that makes the RunWorkerCompleted event run on the UI thread. There is no code that you wrote that made it run so the debugger cannot show anything relevant but the last statement that is in your program that was still involved, the Application.Run() call that started the message loop.

You have to debug this by forcing the debugger to stop when the exception is thrown. Debug + Exceptions, tick the Thrown checkbox for CLR exceptions. Also note the behavior when you run this without a debugger, you'll get the Wheel Of Fortune dialog. Fix that with Application.SetUnhandledExceptionMode().