Determining that the Application want to quit from within a thread

  • Thread starter Thread starter ozbear
  • Start date Start date
O

ozbear

My scenario ws that I had a small group of worker threads
started from the main Application thread, and they have the
backgroundthread property set to true.

After having been started by the main thread, a given worker
thread does some work in a loop and uses the Control.Invoke
method to update the application main form. The control is
set in a thread property before the thread's Start method is
called and the delegate invoked does some updating on the control.

This is the proper way of doing things as far as I know since a thread
should never do any direct updating of a visual element that
is created by another thread.

My problem is that while the thread(s) are running, if the
user clicks on the main form's "X" button to close the form/
terminate the application, the threads so not automagically
die, or at least the application goes to 100% CPU utilisation
waiting for the somethread.IsAlive property to become false.

I would have expected some exception to be thrown within the
thread trying to perform the Control.Invoke method call on
a control (the form) that is closed.

While the Application object has an OnExit event there does not
appear to ba any Application property that can be looked at to
indicate that the Application is terminating. I have had to
resort to introducing a boolean variable set in the Application's
OnExit event handler to true and changing the
while (somethread.IsAlive) loop to...
while (!app_is_terminating && somethread.IsAlive)
to get a clean exit.

Is there a better way?

Regards, Oz
 
Hi, ozbear

you might check state of the control before doing Invoke using
Control.IsDisposed, Created and IsDisposing properties. Also, a good idea
would be to have some global flag, which is set on when app is closing, and
which can be checked by threads.

HTH
Alex
 
Hi, ozbear

you might check state of the control before doing Invoke using
Control.IsDisposed, Created and IsDisposing properties. Also, a good idea
would be to have some global flag, which is set on when app is closing, and
which can be checked by threads.

HTH
Alex
<snip>

Yes, a global flag is what I decided upon although it isn't the
thread that checks it (nor did that actually help). The problem
occurred during the main application thread waiting for the
thread(s) to complete, via their IsAlive property.

Changing the while loop waiting for thread terminations from...
while (thread[k].IsAlive) DoEvents();
to....
while (!application_closing && thread[k].IsAlive) DoEvents();
seems to have done the trick, due to the short-circuit evaluation of
the && operator, and the threads being background threads, so they
will get snuffed anyhow.

The Application object really needs such a global flag built-in to it
rather than us having to introduce a global flag and setting it
in the Application.OnExit event handler.

Thanks for the reply,
Oz
 
What kind of worker threads are these? If you created them yourself, then
make sure you set the IsBackground property on the worker threads to true -
this allows your application to exit even while the worker threads are
running. When the last foreground thread has terminated the runtime will
begin to shutdown the process.

You can also detect when the application is terminating after the shutdown
procedure has begun by examining the Environment.HasShutdownStarted
property.



ozbear said:
Hi, ozbear

you might check state of the control before doing Invoke using
Control.IsDisposed, Created and IsDisposing properties. Also, a good idea
would be to have some global flag, which is set on when app is closing, and
which can be checked by threads.

HTH
Alex
<snip>

Yes, a global flag is what I decided upon although it isn't the
thread that checks it (nor did that actually help). The problem
occurred during the main application thread waiting for the
thread(s) to complete, via their IsAlive property.

Changing the while loop waiting for thread terminations from...
while (thread[k].IsAlive) DoEvents();
to....
while (!application_closing && thread[k].IsAlive) DoEvents();
seems to have done the trick, due to the short-circuit evaluation of
the && operator, and the threads being background threads, so they
will get snuffed anyhow.

The Application object really needs such a global flag built-in to it
rather than us having to introduce a global flag and setting it
in the Application.OnExit event handler.

Thanks for the reply,
Oz
--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Yes, such global property in Application class might be handy if it handles
all situations - including killing process, shutdowns and closing windows.
As about loop - you might be better off using standard Join method. See
Thread.Join.

HTH
Alex

ozbear said:
Hi, ozbear

you might check state of the control before doing Invoke using
Control.IsDisposed, Created and IsDisposing properties. Also, a good idea
would be to have some global flag, which is set on when app is closing, and
which can be checked by threads.

HTH
Alex
<snip>

Yes, a global flag is what I decided upon although it isn't the
thread that checks it (nor did that actually help). The problem
occurred during the main application thread waiting for the
thread(s) to complete, via their IsAlive property.

Changing the while loop waiting for thread terminations from...
while (thread[k].IsAlive) DoEvents();
to....
while (!application_closing && thread[k].IsAlive) DoEvents();
seems to have done the trick, due to the short-circuit evaluation of
the && operator, and the threads being background threads, so they
will get snuffed anyhow.

The Application object really needs such a global flag built-in to it
rather than us having to introduce a global flag and setting it
in the Application.OnExit event handler.

Thanks for the reply,
Oz
--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Yes, such global property in Application class might be handy if it handles
all situations - including killing process, shutdowns and closing windows.
As about loop - you might be better off using standard Join method. See
Thread.Join.
<snip>

Good idea about Thread.Join!

I should have thought about that.

Oz
 
What kind of worker threads are these? If you created them yourself, then
make sure you set the IsBackground property on the worker threads to true -
this allows your application to exit even while the worker threads are
running. When the last foreground thread has terminated the runtime will
begin to shutdown the process.

You can also detect when the application is terminating after the shutdown
procedure has begun by examining the Environment.HasShutdownStarted
property.
<snip>

As I said in my original message, I had already /done/ that. The
IsBackground property was set to true but the main thread got held
up forever waiting for somethread[h].IsAlive to become false.

Never happened.

I'll look into the Environment.HasShutDownStarted...thanks...

Oz
 
Yes, such global property in Application class might be handy if it handles
all situations - including killing process, shutdowns and closing windows.
As about loop - you might be better off using standard Join method. See
Thread.Join.
<snip>

Good idea about Thread.Join!

I should have thought about that.

Oz
 
Back
Top