Deadlock encountered during call to Invoke

G

Guest

Hey guys,

I'm getting into a deadlock condition every once in a while when running my
app. When I see that it's deadlocked I "Break All" in the VS debugger and
take a look at what the current running threads are doing. I noticed that
one of my threads (the one I expect to be running at the time) is waiting in
a call to Invoke. Here is the stack trace:
mscorlib.dll!System.Threading.WaitHandle.WaitOne(long timeout, bool exitContext) + 0x2e bytes
mscorlib.dll!System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, bool exitContext) + 0x23 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle waitHandle = {System.Threading.ManualResetEvent}) + 0xa1 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control caller, System.Delegate method, object[] args, bool synchronous) + 0x36d bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.Invoke(System.Delegate method, object[] args) + 0x48 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.Invoke(System.Delegate method) + 0x7 bytes
Test.dll!ReqForm.OnUpdateStarted() Line 1059 + 0x24 bytes C#


I see that the Invoke method is waiting after a call to WaitOne. Can
someone explain to me what exactly it's waiting on?

Lets say the call was Invoke(new MethodInvoker(OnUpdateStarted));
It didn't start running OnUpdateStarted yet since I would see some logging
indicating that it started.

Any tips on how to figure out what it's waiting on?
Also, when I use BeginInvoke, I do not see the problem (at least not yet).

Thanks.
 
J

Jon Skeet [C# MVP]

Flack said:
I see that the Invoke method is waiting after a call to WaitOne. Can
someone explain to me what exactly it's waiting on?

Lets say the call was Invoke(new MethodInvoker(OnUpdateStarted));
It didn't start running OnUpdateStarted yet since I would see some logging
indicating that it started.

Any tips on how to figure out what it's waiting on?
Also, when I use BeginInvoke, I do not see the problem (at least not yet).

When you call Invoke, that waits until the UI thread has executed the
delegate before the worker thread continues.

You may have a deadlock if your worker thread is holding a lock which
the UI thread needs to acquire before it can finish executing your
delegate.
 
R

richie5um

Hi,

This may or may not be your problem, but it sounds related to
something I encountered awhile ago. Basically I was seeing exactly
the same lock-up issue, even though I had correctly used Invoke/
BeginInvoke to handle all of the cross-thread UI functionality. On my
application I had a background thread that was updating the UI
components.

After a lot of head scratching I eventually found the problem -
because the handles are lazy created you have to be very careful with
when they get created, as they assume the thread ID of the calling
process, and not the original UI thread. Hence, if you call
"InvokeRequired" on a handle *before* that handle has been created, it
actually gets created within that call. And even though you have
correctly used it, the InvokeRequired will not only associate the
Handle with the wrong thread, but will return "false", even though
this is not the UI thread.

In the end, the simple solution was to call "IntPtr intPtr =
control.Handle;" immediately after I had created the control, thus
forcing its creation on the correct thread.

I then wrote a number of helpermethods to wrap the InvokeRequired
functionality behind single static helper methods - I put these into a
common module that I then reuse over all of my applications, e.g. ( in
this example you would call "UpdateControlText( yourControl,
yourText )" ):
private delegate void DelegateUpdateControlText( Control
_control, string _strText );

public static void UpdateControlText( Control _control, string
_strText )
{
if ( true != _control.InvokeRequired )
{
PerformUpdateControlText( _control, _strText );
}
else
{
_control.Invoke( new
DelegateUpdateControlText( ControlHelper.PerformUpdateControlText ),
new object[] { _control, _strText } );
}
}

private static void PerformUpdateControlText( Control
_control, string _strText )
{
_control.Text = _strText;
}


regards,
RichS
 
G

Guest

Thanks for the answers. I'm still not clear on what is happening though. The
UI thread is running fine and responding. I can use my app as normal. It's
just that the form that the Invoke call was made on doesn't ever start the
delegate that the Invoke call was called with.

Can this happen? That the Invoke call is waiting not on the UI thread but
on something else or am I missing something?

Thanks.
 
J

Jon Skeet [C# MVP]

Flack said:
Thanks for the answers. I'm still not clear on what is happening though. The
UI thread is running fine and responding. I can use my app as normal. It's
just that the form that the Invoke call was made on doesn't ever start the
delegate that the Invoke call was called with.

Can this happen? That the Invoke call is waiting not on the UI thread but
on something else or am I missing something?

Sounds odd to me.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top