Application.DoEvents()

  • Thread starter Thread starter Alan T
  • Start date Start date
A

Alan T

I tried to use a thread to process a iterative execution of processes but
afraid my thread is not thread-safe.
If I am not using a thread, my main form will become 'white' when switch
forth and fro between other applications. So now I tried
Application.DoEvents(). But it seems does not help, my main form still
displays as 'white' when switch between other application.
 
Hi Alan,

What Application.DoEvents is doing is halt the current processing and
process pending events before continuing, but to make your form responsive
you would need to call DoEvents several times per second. If you are
unable to split your processing into small chunks that can be interrupted
with a DoEvents, you will need to use another thread.
 
So this is basically what I am doing:
Press a button on main form, execute a loop, execute a third party
application inside each loop.

Click other applicaton on task bar and click my application, my main form is
white now.
 
| So this is basically what I am doing:
| Press a button on main form, execute a loop, execute a third party
| application inside each loop.
|

What exactly do you mean here? you can't execute another application withing
an application!
Please post some code, or be more explicit.

Willy.
 
Sorry if my explanation was not clear:

I got a main form, by pressing a button a looping process will be executed
(while loop), for example 100 times.
Inside this loop, I will execute a third-party application (eg. abc.exe).

This is so far so good.

However, if I click other application on the taskbar, for example, Windows
Explorer, IE,... etc and then click my application, my main form will be
blank.
So what I think is I need to add Application.DoEvents() inside my while
loop.

After I added Application.DoEvents() in some places inside my click event
handler and inside my while loop, it gave some improvements. But sometimes
the response is still so slow and sometimes gave me blank screen on my main
form.
 
Just to add to what Morten said, you should never ever execute something
that takes more than a couple of 100 msec. (and even this might be
disturbing) inside a UI handler. In your handler you are spawning an
external application and you probably wait until this external process
terminates (you better do so!), this will take longer than a few 100 msec,
right?, well don't do this, handle this to an auxiliary thread, and you
don't need this DoEvents any longer.

Willy.




| Sorry if my explanation was not clear:
|
| I got a main form, by pressing a button a looping process will be executed
| (while loop), for example 100 times.
| Inside this loop, I will execute a third-party application (eg. abc.exe).
|
| This is so far so good.
|
| However, if I click other application on the taskbar, for example, Windows
| Explorer, IE,... etc and then click my application, my main form will be
| blank.
| So what I think is I need to add Application.DoEvents() inside my while
| loop.
|
| After I added Application.DoEvents() in some places inside my click event
| handler and inside my while loop, it gave some improvements. But sometimes
| the response is still so slow and sometimes gave me blank screen on my
main
| form.
|
| | >
| > | > | So this is basically what I am doing:
| > | Press a button on main form, execute a loop, execute a third party
| > | application inside each loop.
| > |
| >
| > What exactly do you mean here? you can't execute another application
| > withing
| > an application!
| > Please post some code, or be more explicit.
| >
| > Willy.
| >
| >
|
|
 
I tried a using thread and it solved my problem.
But, how do I detect the thread is finished ?
 
Alan said:
I tried a using thread and it solved my problem.
But, how do I detect the thread is finished ?

You don't actually "detect" that the thread is finished.

Instead, you have the method that runs in the background thread use
this.Invoke to make a call to another method, this time back in the UI
context, and in there do whatever you need to do now that the thread is
finished.

For example, I do some heavy processing when a user presses a button.

1. The button1_Clicked method that handles the button click disables
all of the controls on the form and then starts a new thread and has it
run DoHeavyProcessing.

2. At the end of DoHeavyProcessing, I do a this.Invoke() to run
DoneProcessing method on the UI thread.

3. DoneProcessing() then re-enables all of the controls on the form.

The final effect is that when the user presses the button, the form
changes so that he can't manipulate anything, but he can still minimize
it, maximize it, drag it around, etc. When the background process is
done the form's controls are re-enabled and the user can continue
working.
 
Can you elaborate about step (2) ?
How does the DoneProcessing on the UI thread be called by this.Invoke() ?
 
Hi Alan

Can you elaborate about step (2) ?
How does the DoneProcessing on the UI thread be called by this.Invoke() ?


You create a Delegate and use the Delegate to notify the proper method
The code below will disable the controls on the form while
DoHeavyProcessing is doing some work (sleeping for five seconds)

public delegate void ProcessingDelegate();

private void button1_Click(object sender, EventArgs e)
{
foreach (Control c in this.Controls)
c.Enabled = false;

Thread t = new Thread(new ThreadStart(DoHeavyProcessing));
t.Start();
}

private void DoneProcessing()
{
foreach (Control c in this.Controls)
c.Enabled = true;
}

private void DoHeavyProcessing()
{
Thread.Sleep(5000);

ProcessingDelegate d = new ProcessingDelegate(DoneProcessing);

this.Invoke(d);
}
 
Hi Bruce,

There is no ProcessingDelegate in the framework, that is just a name for a
delegate, and delegates have been around since framework 1.1.

I was not aware of MethodInvoker, but after reading some documentations
(MSDN) I would not recommend using it. There is no listed overload for
Control.Invoke that takes MethodInvoker as parameter, which indicates that
this is not a supported feature. Furthermore, the documentations for
MethodInvoker states that it is an internal method and should not be used
in code. Nor does it support Compact Framework (which delegate does).
 
It indicates no such thing!

Control.Invoke has two overloads; both accept a System.Delegate, with one
also accepting parameters. This means that *any* delegate (i.e. class
derived from System.Delegate) can be used.

Note that System.Delegate is abstract, so by your logic *no* usage of
Control.Invoke is supported.

In short; MethodInvoker is just fine. All it means is "a delegate with void
return and no parameters". No more, no less. I can't see any "internal"
warning on MSDN... can you reference this?

As for "delegate" (note lower "d") being supported on the compact
framework... "delegate" is a keyword, not a type. Delegate is a type, but is
abstract. You need to talk in concrete terms here. The only reason
MethodInvoker isn't on CF is because it happens to be located in
Windows.Forms; however, logically it is identical to ThreadStart... which is
supported in CF1.0 and CF2.0.

So if you need "MethodInvoker" usage on CF, either just use ThreadStart, or
(if this gets confusing to people) declare your own:

public delegate void MethodInvoker();

IMHO.

Marc
 
Additional:

"Remarks" from MSDN2 (MSDN differs by a "don't" <=> "do not")
http://msdn2.microsoft.com/en-us/library/system.windows.forms.methodinvoker.aspx

<quote>MethodInvoker provides a simple delegate that is used to invoke a
method with a void parameter list. This delegate can be used when making
calls to a control's Invoke method, or when you need a simple delegate but
do not want to define one yourself.</quote>

Sounds fairly public (non-internal) to me... and it explicitely states that
it *is* suitable for use with "a control's Invoke method".

Marc
 
The mists part and all becomes clear...

Easily done... an unfortunate name conflict, and I concur: I doubt that
this version of MethodInvoker would be supported by winforms ;-p

If it helps, I've had much bigger "oops" moments myself (of my own
doing) ;-p

Regards,

Marc
 

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

Back
Top