By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,497 Members | 1,287 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,497 IT Pros & Developers. It's quick & easy.

DoEvents() "Hangs"

P: n/a
Group:

We have an application that is calling a stored proc. The stored proc
takes anywhere from 15 to 90 minutes to run.

In order to keep the GUI responsive, we are using a BackgroundWorker to
actually make the call to the stored proc. The app then sits in a loop
that awakes every second and updates an elapsed time value.

The problem that we are having is that after a certain period of time -
which is rarely the same amount - the call to DoEvents hangs (does not
return).

I was hoping the group could help us with: a) why thiat might be
occuring and b) what if anything can be done to fix it.

Here's the key areas of the code:

This is from the method that starts the ball rolling:
Aug 3 '06 #1
Share this Question
Share on Google+
15 Replies


P: n/a
Hello ce******@ocv.com,

Do people really still use DoEvents() (is it even valid in C#?). You should
be using Thread.Join or Thread.Sleep (or a synchronization semantic like
a Mutex or Monitor).
Thanks,
Shawn Wildermuth
Speaker, Author and C# MVP
http://adoguy.com
Group:

We have an application that is calling a stored proc. The stored proc
takes anywhere from 15 to 90 minutes to run.

In order to keep the GUI responsive, we are using a BackgroundWorker
to actually make the call to the stored proc. The app then sits in a
loop that awakes every second and updates an elapsed time value.

The problem that we are having is that after a certain period of time
- which is rarely the same amount - the call to DoEvents hangs (does
not return).

I was hoping the group could help us with: a) why thiat might be
occuring and b) what if anything can be done to fix it.

Here's the key areas of the code:

This is from the method that starts the ball rolling:
.
.
.
case "Consolidate Revenue": {
bgwThread.RunWorkerAsync( cConsolidateRevenue );
SleepAndUpdate();
break;
}
.
.
.
This is from the "DoWork" event handler:

private void bgwThread_DoWork( object sender, DoWorkEventArgs e )
{
switch ((int)e.Argument) {
case cConsolidateRevenue: {
ConsolidateRevenue( cn, dtPickerStartDate.Value.Date,
dateImportEndDate );
break;
}
.
.
.
Here is SleepAndUpdate:
private void SleepAndUpdate( ) {
while (notDone) {
ShowElapsedTime();
Application.DoEvents();
System.Threading.Thread.Sleep( 1000 );
}
}
We have verfied that the app is indeed haning on the call to
DoEvents()

Thank you for your help

Aug 3 '06 #2

P: n/a
Why are you having the front end stop if you are running the operation on a
background thread anyways?

Couldn't you just make the background thread tell the front end when it is
done through a callback/event/etc

Cheers,

Greg Young
MVP - C#
http://codebetter.com/blogs/gregyoung

<ce******@ocv.comwrote in message
news:11**********************@75g2000cwc.googlegro ups.com...
Group:

We have an application that is calling a stored proc. The stored proc
takes anywhere from 15 to 90 minutes to run.

In order to keep the GUI responsive, we are using a BackgroundWorker to
actually make the call to the stored proc. The app then sits in a loop
that awakes every second and updates an elapsed time value.

The problem that we are having is that after a certain period of time -
which is rarely the same amount - the call to DoEvents hangs (does not
return).

I was hoping the group could help us with: a) why thiat might be
occuring and b) what if anything can be done to fix it.

Here's the key areas of the code:

This is from the method that starts the ball rolling:
.
.
.
case "Consolidate Revenue": {
bgwThread.RunWorkerAsync( cConsolidateRevenue );
SleepAndUpdate();
break;
}
.
.
.

This is from the "DoWork" event handler:

private void bgwThread_DoWork( object sender, DoWorkEventArgs e ) {
switch ((int)e.Argument) {
case cConsolidateRevenue: {
ConsolidateRevenue( cn, dtPickerStartDate.Value.Date,
dateImportEndDate );
break;
}
.
.
.

Here is SleepAndUpdate:
private void SleepAndUpdate( ) {
while (notDone) {
ShowElapsedTime();
Application.DoEvents();
System.Threading.Thread.Sleep( 1000 );
}
}
We have verfied that the app is indeed haning on the call to DoEvents()

Thank you for your help

Aug 3 '06 #3

P: n/a
The business requirements are such that the call needs to be
synchronous but the GUI needs to be semi-responsive while it is
running.

The users are not able to perform any other taks in the app while the
call is being processed but when the process is long running they
don't want the screen to "white" out either.

That is the only reason for the threading.

Aug 3 '06 #4

P: n/a
Then you need to just disable the GUI programmitically. Thread.Sleep()
on the UI thread is never correct. Look into using the BackgroundWorker
class for a simple and sound solution if you're using 2.0.

http://msdn2.microsoft.com/en-us/lib...undworker.aspx

ce******@ocv.com wrote:
The business requirements are such that the call needs to be
synchronous but the GUI needs to be semi-responsive while it is
running.

The users are not able to perform any other taks in the app while the
call is being processed but when the process is long running they
don't want the screen to "white" out either.

That is the only reason for the threading.
Aug 3 '06 #5

P: n/a
Exactly, I am using the BackgroundWorker (see code snippets) above. In
essence, I am firing off the stored proc and then putting the GUI in a
loop that sleeps for a while, awakens, and updates itself and then goes
back to sleep. This continues until the stored proc returns.

But the trouble is that it (the SleepAndUpdate loop) stops working
after a while. When it first fires up, everything is great and then
after an indeterminate period of time the DoEvents() stops returning.

It is puzzling.

I hate to take the "easy" way out and point to the framework but that
is indeed what it seems like the trouble is.

All helpful thoughts and suggestions (not the snarky ones about "Do
people really still use DoEvents() (is it even valid in C#?).") are
appreciated.

wf****@gmail.com wrote:
Then you need to just disable the GUI programmitically. Thread.Sleep()
on the UI thread is never correct. Look into using the BackgroundWorker
class for a simple and sound solution if you're using 2.0.

http://msdn2.microsoft.com/en-us/lib...undworker.aspx
Aug 3 '06 #6

P: n/a
Don't sleep on the UI thread. Ever. You're preventing the UI
thread from processing any messages for 1 second. Disable the main form
and its controls or launch another simple modal form to actually launch
the processing thread and display some sort of "I'm running" indicator
until it receives notification (not by polling, by callback) that the
thread has finished.
Your implementation is broken, not the framework. This is not meant
to be snarky, just straightforward.

ce******@ocv.com wrote:
Exactly, I am using the BackgroundWorker (see code snippets) above. In
essence, I am firing off the stored proc and then putting the GUI in a
loop that sleeps for a while, awakens, and updates itself and then goes
back to sleep. This continues until the stored proc returns.

But the trouble is that it (the SleepAndUpdate loop) stops working
after a while. When it first fires up, everything is great and then
after an indeterminate period of time the DoEvents() stops returning.

It is puzzling.

I hate to take the "easy" way out and point to the framework but that
is indeed what it seems like the trouble is.

All helpful thoughts and suggestions (not the snarky ones about "Do
people really still use DoEvents() (is it even valid in C#?).") are
appreciated.

wf****@gmail.com wrote:
Then you need to just disable the GUI programmitically. Thread.Sleep()
on the UI thread is never correct. Look into using the BackgroundWorker
class for a simple and sound solution if you're using 2.0.

http://msdn2.microsoft.com/en-us/lib...undworker.aspx
Aug 3 '06 #7

P: n/a
wfa:

Sorry, I wasn't indicting you. I just get frustrated with condescending
posts.

In any case, the issue is that when the call returns then we must move
onto the next step in the process. We let the stored proc run in the
back ground BUT we can't continue on with processing until the stored
proc returns. That is why we go into a sleep loop. Otherwise, we just
loop until the semaphore is reset.

wfa...@gmail.com wrote:
Don't sleep on the UI thread. Ever. You're preventing the UI
thread from processing any messages for 1 second. Disable the main form
and its controls or launch another simple modal form to actually launch
the processing thread and display some sort of "I'm running" indicator
until it receives notification (not by polling, by callback) that the
thread has finished.
Your implementation is broken, not the framework. This is not meant
to be snarky, just straightforward.
Aug 3 '06 #8

P: n/a
I agree with this completely.

You can just leave the UI doing nothing and wait on an event from the worker
thread (i.e. with a modal dialog). This is a quite common task (and many
people include "cancel" buttons on such a screen so the user can stop what
they are doing).

Personally I would also question the business requirement of having a user
on the system unable to use their interface for 15-90 minutes as this sounds
exactly like the type of job that should be done by some system service. By
putting the requirement that the person can't do anything when this is
happenning also leads directly to the conclusion that noone can be doing
anything while this happens on the database (or atleast touching the same
data).

Cheers,

Greg

<wf****@gmail.comwrote in message
news:11**********************@i42g2000cwa.googlegr oups.com...
Don't sleep on the UI thread. Ever. You're preventing the UI
thread from processing any messages for 1 second. Disable the main form
and its controls or launch another simple modal form to actually launch
the processing thread and display some sort of "I'm running" indicator
until it receives notification (not by polling, by callback) that the
thread has finished.
Your implementation is broken, not the framework. This is not meant
to be snarky, just straightforward.

ce******@ocv.com wrote:
>Exactly, I am using the BackgroundWorker (see code snippets) above. In
essence, I am firing off the stored proc and then putting the GUI in a
loop that sleeps for a while, awakens, and updates itself and then goes
back to sleep. This continues until the stored proc returns.

But the trouble is that it (the SleepAndUpdate loop) stops working
after a while. When it first fires up, everything is great and then
after an indeterminate period of time the DoEvents() stops returning.

It is puzzling.

I hate to take the "easy" way out and point to the framework but that
is indeed what it seems like the trouble is.

All helpful thoughts and suggestions (not the snarky ones about "Do
people really still use DoEvents() (is it even valid in C#?).") are
appreciated.

wf****@gmail.com wrote:
Then you need to just disable the GUI programmitically. Thread.Sleep()
on the UI thread is never correct. Look into using the BackgroundWorker
class for a simple and sound solution if you're using 2.0.

http://msdn2.microsoft.com/en-us/lib...undworker.aspx

Aug 3 '06 #9

P: n/a
Have the background thread notify the foreground thread when it is complete
.....

Also you can't continue with the process involving the sproc but can you do
other things while waiting or is the app designed to only do this one
process and the one process doesn't make sense to be doing multiples (i.e.
running a big report).

Cheers,

Greg
<ce******@ocv.comwrote in message
news:11*********************@m73g2000cwd.googlegro ups.com...
wfa:

Sorry, I wasn't indicting you. I just get frustrated with condescending
posts.

In any case, the issue is that when the call returns then we must move
onto the next step in the process. We let the stored proc run in the
back ground BUT we can't continue on with processing until the stored
proc returns. That is why we go into a sleep loop. Otherwise, we just
loop until the semaphore is reset.

wfa...@gmail.com wrote:
>Don't sleep on the UI thread. Ever. You're preventing the UI
thread from processing any messages for 1 second. Disable the main form
and its controls or launch another simple modal form to actually launch
the processing thread and display some sort of "I'm running" indicator
until it receives notification (not by polling, by callback) that the
thread has finished.
Your implementation is broken, not the framework. This is not meant
to be snarky, just straightforward.

Aug 3 '06 #10

P: n/a
Yes, well, while I won't defend the architecture, we are constrained to
work within it.

I did try removing the Sleep from the wait loop. Oddly enough, this
caused the DoEvents to hang sooner. This led us to make the sleep
longer which seems to make the situation better though the hanging
still occurs - just much later in the process.

Using a Modal dialog box is a solution but we are still faced with the
GUI not responding to simple redraw messages.

We believe that will the current solution is ugly it should still work.
We remain puzzled that the DoEvents will work but then suddenly stop
responding.

Greg Young wrote:
I agree with this completely.

You can just leave the UI doing nothing and wait on an event from the worker
thread (i.e. with a modal dialog). This is a quite common task (and many
people include "cancel" buttons on such a screen so the user can stop what
they are doing).

Personally I would also question the business requirement of having a user
on the system unable to use their interface for 15-90 minutes as this sounds
exactly like the type of job that should be done by some system service. By
putting the requirement that the person can't do anything when this is
happenning also leads directly to the conclusion that noone can be doing
anything while this happens on the database (or atleast touching the same
data).

Cheers,

Greg
Aug 3 '06 #11

P: n/a
Note that I said to use a modal dialog and an event/call back.

You would start the thread .... then just sit and do nothing (just show your
screen maybe with a cancel button). There is no loop (well there is but its
not in your code). Later your thread will raise the event or directly call
you back at which point you continue your processing.

Cheers,

Greg
<ce******@ocv.comwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...
Yes, well, while I won't defend the architecture, we are constrained to
work within it.

I did try removing the Sleep from the wait loop. Oddly enough, this
caused the DoEvents to hang sooner. This led us to make the sleep
longer which seems to make the situation better though the hanging
still occurs - just much later in the process.

Using a Modal dialog box is a solution but we are still faced with the
GUI not responding to simple redraw messages.

We believe that will the current solution is ugly it should still work.
We remain puzzled that the DoEvents will work but then suddenly stop
responding.

Greg Young wrote:
>I agree with this completely.

You can just leave the UI doing nothing and wait on an event from the
worker
thread (i.e. with a modal dialog). This is a quite common task (and many
people include "cancel" buttons on such a screen so the user can stop
what
they are doing).

Personally I would also question the business requirement of having a
user
on the system unable to use their interface for 15-90 minutes as this
sounds
exactly like the type of job that should be done by some system service.
By
putting the requirement that the person can't do anything when this is
happenning also leads directly to the conclusion that noone can be doing
anything while this happens on the database (or atleast touching the same
data).

Cheers,

Greg

Aug 3 '06 #12

P: n/a
Well you are constrained to the architecture but it is up to you as the
engineers to build a solid implementation. We are not trying to offend
you (or whoever designed this originally and now seems married to it)
but we're trying to get the point across that your current design is
broken. Get rid of DoEvents and get rid of Sleep, you don't need either
one of them. It will only work if you're lucky, the solutions we're
pushing will work reliably. Don't sit there puzzling over it for
another minute. Take 30 minutes and rewrite it correctly.

cedmu...@ocv.com wrote:
Yes, well, while I won't defend the architecture, we are constrained to
work within it.

I did try removing the Sleep from the wait loop. Oddly enough, this
caused the DoEvents to hang sooner. This led us to make the sleep
longer which seems to make the situation better though the hanging
still occurs - just much later in the process.

Using a Modal dialog box is a solution but we are still faced with the
GUI not responding to simple redraw messages.

We believe that will the current solution is ugly it should still work.
We remain puzzled that the DoEvents will work but then suddenly stop
responding.

Greg Young wrote:
I agree with this completely.

You can just leave the UI doing nothing and wait on an event from the worker
thread (i.e. with a modal dialog). This is a quite common task (and many
people include "cancel" buttons on such a screen so the user can stop what
they are doing).

Personally I would also question the business requirement of having a user
on the system unable to use their interface for 15-90 minutes as this sounds
exactly like the type of job that should be done by some system service. By
putting the requirement that the person can't do anything when this is
happenning also leads directly to the conclusion that noone can be doing
anything while this happens on the database (or atleast touching the same
data).

Cheers,

Greg
Aug 3 '06 #13

P: n/a
Hi,
We believe that will the current solution is ugly it should still work.
We remain puzzled that the DoEvents will work but then suddenly stop
responding.
Well I hope you take some of the very good advice you have been given so
far, but I must admit I do agree with your statement here. Hangs like this
can be caused by deadlocks though you haven't shown enough code to tell us
much there. I also wonder if your thread code might be poking its nose into
UI components in a non thread safe way?

Cheers
Doug Forster
Aug 4 '06 #14

P: n/a
Doug Forster wrote:
Hi,
>We believe that will the current solution is ugly it should still
work. We remain puzzled that the DoEvents will work but then
suddenly stop responding.

Well I hope you take some of the very good advice you have been given
so far, but I must admit I do agree with your statement here. Hangs
like this can be caused by deadlocks though you haven't shown enough
code to tell us much there. I also wonder if your thread code might
be poking its nose into UI components in a non thread safe way?
....which is to say, in any way at all.

My first thought on reading the initial post in this thread was that the
background thread is trying to update the UI without going through
Control.{Begin}Invoke - that's a sure recipe for UI hangs like this. But
since he's apparaently using .NET 2.0, I doubt that's the case, since the
2.0 Winforms classes will throw an exception if you touch them from the
wrong thread.

I agree completely with the other advice in this thread: get rid of the
sleep/doEvents loop and put up a modal form, or just disable the main form
until a callback (or event) from the worker thread indicates that it's time
to move on to the next step.

-cd


Aug 4 '06 #15

P: n/a
On 3 Aug 2006 13:36:40 -0700, ce******@ocv.com wrote:
>All helpful thoughts and suggestions (not the snarky ones about "Do
people really still use DoEvents() (is it even valid in C#?).") are
appreciated.
That may have been snarky but it was absolutely correct.
Do not use DoEvents, ever! There is never a good reason to have the
operating system perform unpredictable reentrant calls on the current
GUI thread -- because that's exactly what DoEvents does.
--
http://www.kynosarges.de
Aug 4 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.