Finding Out Why Control.Invoke Throws Undocumented Exceptions

A colleague was baffled by having Control.Invoke (when called from a different thread) throw an ArgumentException at him and asked if I knew what was happening. Opening the stack trace, I found that the exception originated from Control.MarshaledInvoke:

       at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
[ user code...]

This meant that the exception was either raised from an undocumented source or that the exception had been rethrown with the original stack trace deleted.

To debug this further, I changed Invoke to BeginInvoke. to see if it might make a difference. This raised, instead of an ArgumentException, a TargetInvocationException, which in turn contained the original exception with its original stack trace. The problem was found and fixed.

Advertisements

5 thoughts on “Finding Out Why Control.Invoke Throws Undocumented Exceptions

  1. Excellent. Thank you very much for this. This helped me diagnose the source of an issue I was receiving on an Invoke, receiving the not very useful “The Input String was not in a correct format” exception. Changing the Invoke to BeginInvoke allowed me to interrogate the InnerException and find the real culprit.

  2. Thanks!
    This helped me track down a problem too.
    The ex was: “The Input String was not in a correct format”
    The problem: an event handler was doing:
    Console.writeLine(“blah blah ” + anIntegerValue + ” blah.”)
    Hint: use “.toString()”, or use the ” & ” string concat operator instead of the ” + ” addition operator.
    -ME

  3. That’s just helped me out too. My Invoke now looks like this:
    // If we’ve been called from the wrong thread, try again.
    if(InvokeRequired)
    {
    // Why not a simple call to Invoke? Because callstacks are truncated in an unhelpful way.
    var result = BeginInvoke(new Frm.Support.Threading.TaskHandler(UpdateGrid));
    if(!result.CompletedSynchronously)
    result.AsyncWaitHandle.WaitOne();
    return;
    }
    And this returns complete callstacks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s