+3  A: 

The cancel event/flag should be a volatile... I asked a very similar question to yours: http://stackoverflow.com/questions/2474945/is-it-safe-to-use-a-boolean-flag-to-stop-a-thread-from-running-in-c

I would also recommend that when you cancel your threads you wait for all of them to cancel by using something similar to the C# version of CountDownLatch. It's useful when you want to guarantee that the thread is canceled.

Lirik
Yours was the question I was trying to find in my searches!
rnd
@rnd, glad I could help!
Lirik
+1  A: 

It will ultimately always result in something like this - although it's important that you make your cancel variable volatile, as otherwise the worker threads may not see the change from the cancelling thread.

You've got to check something periodically unless you want to go the more drastic route of interrupting the thread (which I don't recommend). Checking a single Boolean flag isn't likely to be exactly costly... if you can do a reasonable chunk of work in each iteration of the loop (enough to dwarf the cost of the check) then that's fine.

If you ever need to perform any waiting, however (in the worker thread), then you may be able to improve matters, by using a form of waiting (e.g. Monitor.Wait) which allows the cancelling thread to wake any waiting threads up early. That won't make normal operation more efficient, but it will allow the threads to terminate more quickly in the event of cancellation.

Jon Skeet
C# in Depth is currently on a truck heading my way from Amazon. Looking forward to it!
rnd
A: 

i would do it the same way. i would also add Thread.Sleep in to the loop to yield control to the main thread.

http://msdn.microsoft.com/en-us/library/7a2f3ay4%28VS.80%29.aspx

akonsu
I don't think that Thread.Sleep is necessary when there is a proper signaling implemented (i.e. Monitor or CountDownLatch).
Lirik
agree, i was talking about a simple variable check inside a loop.
akonsu
+1  A: 

Especially since it's UI-triggered, I would recommend just leveraging the BackgroundWorker that's already in the framework, especially since it'll nicely have the progress and done events happen on the UI thread for you (so you don't have to invoke it over yourself).

Then you can just use the CancelAsync() call. Admittedly, it's not much different than what you're already doing, just done in the framework already (and including the thread synchronization logic)

As Jon mentioned, you're still going to want to do cooperative cancellation (checking CancellationPending in your DoWork for use of BackgroundWorker) since the 'interrupt/abort the thread' option is something you want to avoid if possible.

If in .NET 4 you can use TPL and the new Cancellation support, but again it's focused on cooperative cancellation.

James Manning
Thanks for the tips on background worker, James. I will consider moving over to this rather than my own implementation, since my threading system is a temporary test container at the moment.
rnd
+1  A: 

I recommend using the unified cancellation model that was introduced in .NET 4.0 (if .NET 4.0 is an option).

It is very efficient, and allows integrated cancellation with Task objects and Parallel LINQ.

Stephen Cleary