views:

162

answers:

7
+1  Q: 

Stopping a Thread

Here is the situation. I have a thread that gets started with the click of a button. It then works for approx 2 min (give or take quite a bit) and then finishes, updating the UI and all along the way. It is quite nice. Now I have decided to add a "Cancel" button to the mix. My question would be what is the best approach to stop a thread from the outside? What methods are best to avoid completely? What resources can I look into myself to get some more knowledge on the topic.

One other piece of info. The program was not written by me, I just "inherited" it, and am now trying to expand it's functionality in small ways to make it more user friendly.

EDIT: Working with VS2008 and .NET 3.5

+2  A: 

You should have a flag somewhere that the worker thread checks once in a while. And when the flag says the thread should cancel, it should stop working and exit gracefully.

Svish
+10  A: 

In fact if you want to safely cancel some background operation the best approach is to create private boolean field _isCancelled which will be shared between GUI thread and background thread. If user presses cancel you just set _isCancelled to false. And in the background thread regulary check if _isCancelled is turned to true and return the method.

Mike
Yeah, and also `_isCancelled` should be `volatile`.
Petar Minchev
I really wish that I could vote this answer up more than just one. It helped me out so much. Thanks!
Adkins
Yep, you must use volatile keyword, or lock operator to make sure you always have the correct value of _isCancelled field and avoid thread concurrency.
Mike
+4  A: 

One 'best' way to do this type of stuff in .NET is to use BackgroundWorker.

BackgroundWorker will cleanly handle the progress updates (which you may currently have working only by luck, or by a lot of tedious Invoke() calls), and also provides a clean cancellation mechanism.

BackgroundWorker uses a pool thread rather than a dedicated one, which is also a better approach than some others.

Stopping a thread from outside it is almost always the wrong approach, though to begin with it usually feels like it's what you want to do.

If you're using .NET 4.0, there is a whole new task and cancellation mechanism available as well, but it sounds to me that a study of BackgroundWorker would be a good first point for you.

Will Dean
We are using .NET 3.5 and the thread is a custom creation that comes along with this inherited code. Is the cancellation mechanism native to threads or only to the background worker?
Adkins
@Adkins this is valid for the background worker only.
Marek
I saw that BackgroundWorker has some good built in functionality, but sadly it is not something I can use for this project.
Adkins
+5  A: 

I often use System.ComponentModel.BackgroundWorker in similar cases. On the UI side, call its CancelAsync() method; on the worker thread side, periodically check the CancellationPending property.

Achille
A: 

If you are using .NET 4 try Tasks and their built in cancelation mechanism.

Al Bundy
Updated post to show the .NET version (3.5).
Adkins
+6  A: 

what is the best approach to stop a thread from the outside?

The Thread has to cooperate. You need a shared flag (boolean) and the Thread-code has to check this periodically.

What methods are best to avoid completely?

Thread.Abort().

Henk Holterman
+1  A: 

Rather than going for a shared boolean variable between UI and worker class, a more clearer approach would be to use reset events (AutoResetEvents/ManualResetEvent).

However it still depends on what kind of processing you are doing in the thread. If it is say for example a loop which processes files, the reset event threading constructs can be used. If it's a single operation (e.g copying a huge file) then you have no way of cancelling that, and you also do not know what the thread is currently executing.

It would also help if you know what the user wants by clicking cancel - drop everything that thread is doing or take the application to previous state or finish the current item being processed and return immediately.

thewpfguy