How to shutdown a worker thread when a form is closed?

Use BeginInvoke instead of Invoke.

Let’s assume you are writing a .NET application with a progress bar.

  • It starts a worker thread when the application starts.
  • The worker thread does some lengthy work.
  • The worker thread calls OnProgress() delegate whenever some progress happens.

Since you may not call any Control methods from non-UI thread, the
implementation of OnProgress would be something like this (Use
Control.Invoke):

private void OnProgress(int percent){
Invoke(new MethodInvoker(delegate(){
progressBar.Value = percent;
}));
}

ObjectDisposedException!?

However, you have a problem here. OnProgress() is called from the
worker thread which does not know anything about the UI thread. For
example, it might be called *after* the Form is closed. If it happens,
you get ObjectDisposedException.

How about stopping the worker thread in OnClosed()?

You might want to stop the worker thread in Form.OnClosed() so that OnProgress() cannot be called after Form’s disposal.

protected override void OnClosed(EventArgs e) {
// ...
// cancel worker thread
// ...
workerThread.Join();
base.OnClosed(e);
}

Opps, it’s now dead locked.

Unfortunately, the solution is not right. OnClosed() is called from
UI thread, and it is blocked at Thread.Join(). While it’s blocked,
OnProgress() is also blocked because Invoke() requires the UI thread to
work. (Remember: The delegate passed to Invoke() is executed by the UI
thread.)

So, what should I do?

Use BeginInvoke() instead of Invoke(). BeginInvoke() does not block the caller thread, so the deadlock can be avoided.

How about EndInvoke()?

You might wonder when to call EndInvoke(). If you call EndInvoke(),
the caller thread is blocked until the delegate is processed – it’s
essentially same as Invoke(). Therefore, you have the same deadlock
issue again.

Fortunately, you don’t have to call EndInvoke(). It’s not well
documented in MSDN, but it is "officially" true. See the comments of
the blog entry below:

http://blogs.msdn.com/cbrumme/archive/2003/05/06/51385.aspx

Advertisements

About Moto

Engineer who likes coding
This entry was posted in Tips. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s