Control.Invoke hangs

G

Guest

I have a C# application that consists of a Form and a seperate Engine class. The engine class is run in multiple worker threads and does all the work for the application. When the work that it is doing results in information the user should see, a message is placed in a queue that the Form monitors in order to receive this information and display it.

When the Form receives information to display, it calls Control.Invoke to be sure the updating of the GUI is handled in the main UI thread. After the call to Invoke, the Form goes back to monitoring the queue for additional information to display.

My application typically needs to run for many hours at a time. Typical GUI updates from each piece of data on the GUI happen 10 times per minute. So each of the GUI areas is typically updated every 6 seconds. When my application starts, all of my GUI areas update as expected. However, after a period of time (30-90 minutes) my GUI stops updating.

The cause is that a call to Control.Invoke has blocked (as it is supposed to do) and it has never returned. This is easily verified in the debugger in the IDE.

What would cause the Control.Invoke call to black and never return? Does anyone has any experience with this?

Thank you for your help.
 
J

Jon Skeet [C# MVP]

BJones said:
I have a C# application that consists of a Form and a seperate Engine
class. The engine class is run in multiple worker threads and does
all the work for the application. When the work that it is doing
results in information the user should see, a message is placed in a
queue that the Form monitors in order to receive this information and
display it.

When the Form receives information to display, it calls
Control.Invoke to be sure the updating of the GUI is handled in the
main UI thread. After the call to Invoke, the Form goes back to
monitoring the queue for additional information to display.

My application typically needs to run for many hours at a time.
Typical GUI updates from each piece of data on the GUI happen 10
times per minute. So each of the GUI areas is typically updated every
6 seconds. When my application starts, all of my GUI areas update as
expected. However, after a period of time (30-90 minutes) my GUI
stops updating.

The cause is that a call to Control.Invoke has blocked (as it is
supposed to do) and it has never returned. This is easily verified in
the debugger in the IDE.

What would cause the Control.Invoke call to black and never return?
Does anyone has any experience with this?

Well, the most obvious reason would be if it tried to acquire a lock
which the thread calling Control.Invoke owned. That would block the UI
thread, and you should be able to break into it to find out where it's
blocked.

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.
 
G

Guest

Jon Skeet said:
Well, the most obvious reason would be if it tried to acquire a lock
which the thread calling Control.Invoke owned. That would block the UI
thread, and you should be able to break into it to find out where it's
blocked.

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.

Thanks for the reply, Jon.

Certainly an attempt by the GUI thread to acquire a lock that is already owned by the thread calling Invoke would hang the both threads. This is not the case. The only code executed by the GUI thread when prompted via a call to Invoke is someLabelOnTheForm.Text = textPassedInToDelegate. It is so simple, that there should be no reason that Control.Invoke should ever hang.

I can work on slicing and dicing in order to get a complete program that illustrates this, but taking 8000 lines of code and ripping out just this portion and keeping things functional may prove too challenging.

Brian
 
J

Jon Skeet [C# MVP]

BJones said:
Certainly an attempt by the GUI thread to acquire a lock that is
already owned by the thread calling Invoke would hang the both
threads. This is not the case. The only code executed by the GUI
thread when prompted via a call to Invoke is someLabelOnTheForm.Text
= textPassedInToDelegate. It is so simple, that there should be no
reason that Control.Invoke should ever hang.

Can you see what the GUI thread is actually doing? Perhaps the hang is
somewhat earlier, and the reason Control.Invoke is blocking is that the
UI thread itself is busy doing something else?
I can work on slicing and dicing in order to get a complete program
that illustrates this, but taking 8000 lines of code and ripping out
just this portion and keeping things functional may prove too
challenging.

I think it's the best way to find the problem, to be honest.
 
G

Guest

Jon Skeet said:
Can you see what the GUI thread is actually doing? Perhaps the hang is
somewhat earlier, and the reason Control.Invoke is blocking is that the
UI thread itself is busy doing something else?


I think it's the best way to find the problem, to be honest.

Thanks again for the reply.

The GUI Thread is doing what it normally does when this other thread that calls Invoke hangs on that call. The GUI Thread is often in Application.Run() if broken in the debugger, or it is servicing other form updates and repaints. It is behaving as I would expect.

It is just this call to Control.Invoke that hangs and never returns.

Now, the solution to this, because I care not about the return value of the call to Invoke is to simply use Control.BeginInvoke. In doing this, the worker dispatch thread does not require the marshal to the GUI Thread to return, so he goes on servicing requests.

This fixes the issue, and I have been using this for some time with no problems. However, I still want to get to the bottom of why Control.Invoke would hang and not return.

I also understand that ripping the code apart is possibly the best way to find the problem. I am just sharing that it may not be practical for me to do that at this time.

Thanks again for the continued dialog.

Brian
 
J

Jon Skeet [C# MVP]

BJones said:
Thanks again for the reply.

The GUI Thread is doing what it normally does when this other thread
that calls Invoke hangs on that call. The GUI Thread is often in
Application.Run() if broken in the debugger, or it is servicing other
form updates and repaints. It is behaving as I would expect.

So it can repaint okay?
It is just this call to Control.Invoke that hangs and never returns.

And are all your controls always created on a single thread?
Now, the solution to this, because I care not about the return value
of the call to Invoke is to simply use Control.BeginInvoke. In doing
this, the worker dispatch thread does not require the marshal to the
GUI Thread to return, so he goes on servicing requests.

This fixes the issue, and I have been using this for some time with
no problems. However, I still want to get to the bottom of why
Control.Invoke would hang and not return.

More than that - you've got the worry that your Control.BeginInvoke may
never even end up being used, if you've got the same problem somewhere.
I also understand that ripping the code apart is possibly the best
way to find the problem. I am just sharing that it may not be
practical for me to do that at this time.

Fair enough.
Thanks again for the continued dialog.

No problem - and if you do ever get to the bottom of it, I'd be very
interested to hear what the cause was.
 
K

Ken Varn

I could not help but notice that this problem is very similar to a problem
that I am having as well. For some unknown reason, the Control.Invoke call
in my application hangs as well. I have checked all mutexes for deadly
embraces and found none. It seems to occur after a prolonged period of
running.

I saw in another message that you used BeginInvoke for your message
processing. I thought about doing this as well, but I am concerned about
stacking up requests on the message queue faster than it can pull them off.
My thread is running at a pretty good clip and I don't want to overrun the
message queue.

If you have any other input regarding this problem, please let me know.

--
-----------------------------------
Ken Varn
Senior Software Engineer
Diebold Inc.

EmailID = varnk
Domain = Diebold.com
-----------------------------------
BJones said:
Thanks for the reply, Jon.

Certainly an attempt by the GUI thread to acquire a lock that is already
owned by the thread calling Invoke would hang the both threads. This is not
the case. The only code executed by the GUI thread when prompted via a call
to Invoke is someLabelOnTheForm.Text = textPassedInToDelegate. It is so
simple, that there should be no reason that Control.Invoke should ever hang.
I can work on slicing and dicing in order to get a complete program that
illustrates this, but taking 8000 lines of code and ripping out just this
portion and keeping things functional may prove too challenging.
 
G

Guest

Turns out this is a now a known issue with the .NET 1.1 framework, due to a
race condition in the asynchronous wrapper. MS has a suggested workaround
that works the majority if not all of the time, though we have heard of some
potentially suggestive data where it may still hang with the workaround but
we have not been able to reproduce that or confirm.
 
G

Guest

I should point out the initial condition seems rare and is more likely to
happen with a lot of threads and on a multiprocessor box. It is even more
rare if at all if the workaround fails (unconfirmed). MS reports this issue
has been addressed in VS2005/.NET 2.0.
 
M

Marc Bernard

Do you have a KB number for this?

Marc


WXS said:
I should point out the initial condition seems rare and is more likely to
happen with a lot of threads and on a multiprocessor box. It is even more
rare if at all if the workaround fails (unconfirmed). MS reports this
issue
has been addressed in VS2005/.NET 2.0.
 
G

Guest

No, to my knowledge they have not widely published this information yet.
There may be one that I am not aware of...

It should be in there internal KB's or problem resolutions though since they
helped figure out what was going on.
 
C

colinjack

Hi,

Can I ask if there are any sites that I can get more details from as
this is
causing me trouble too and the work around would be very useful.

Ta,

Colin
 
G

Guest

The work around is simply to use BeginInvoke and then wait on the result with
a timeout. If the timeout happens try waiting on it again, and if it times
out wait on it again, etc.

When the probably does crop up most testing shows the second time you wait
it will continue without timing out. This is due to the async wrapper race
condition issue. We have possible reports of some cases this does not work
but we have not been able to repeat them.
 

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