views:

132

answers:

4

I have a program that will analyzes source code. It can recursively go through a directory to find all projects, and then recursively go through the project to find all source code.

I want to create a cancel process button, which allows the user to stop the code parsing. I run the code parsing in a background worker. I want to be able to watch for the cancel event.

The problem is figuring out how to edit my code so that it will go and check that item and return back to the GUI. The parsing process goes several methods deep.

In a much smaller process, I successfully use a thread-safe singleton that has a bool that says whether or not a cancel has been requested, and stop the loop where it is running.

What would be the best way of working this cancel request into my code?

EDIT: Here is an idea, inspired by John Saunders' answer.

What if I run a background thread in my processing thread that watches for the Cancel Singleton to change, and then throw an exception from that process? Does this seem like good practice? This does not work as intended

EDIT 2: John Saunders' answer seems to be the best for now. I will just throw my own exception when the Singleton is true for now. I'll wait to see if any other solutions are proposed

A: 

You could use the Thread.Abort() function on your background worker thread. This throws a ThreadAbortException which you can catch in any of your methods but which will atomatically be rethrown at the end of the catch blocks.

Also all finally-blocks will be executed.

MartinStettner
A: 

It sounds like you're using the .NET backgroundworker class. I think you can pass a object parameter into the RunWorkerAsync method which then becomes accessible to the background thread in the DoWork event handler argument.

You could then modify that object in the UI thread (for example update a boolean cancel property) and periodically check on it from your background process.

Steve
+2  A: 

Thread.Abort is a bad idea, as it interrupts the thread at an arbitrary point - probably interrupts it where you'd least like to be interrupted.

Set a flag that it seen by the thread being cancelled. Check it at the beginning of each operation. The idea would be to identify places in the code where it is safe to stop, and to check the flag at only those points.

You may find it useful to throw an exception at those points. The exception should be one that is not caught by your code until it reaches the boundary between your code and the UI. At that point, your code would simply return.

John Saunders
I didn't even think to throw an exception!
phsr
Exceptions and multiple threads are a pain in the butt to debug---in general: beware. The debugger + multiple threads = not your friend.
Jared Updike
I was talking about throwing the exception within his separate thread. It would be caught at the boundary, and not escape. Note that this is partially what Thread.Abort does (it throws ThreadAbortException, I think). But this way, it will be thrown only when it's safe to do so.
John Saunders
A: 

There are various ways to perform a cancel on threaded operations; all of which involve the periodic checking of a flag or other value to determine if the thread should continue operating or not.

I would not recommend throwing exceptions for this feature. First of all, cancelling is not an exceptional circumstance, and second, it's overkill for what you're trying to implement.

Instead, you could use a simple, thread-safe boolean flag as a static member of a class accessible from any thread, or use a synchronization object such as a named Mutex. Signalling the synchronization object would then allow the thread to know it must cancel.

Jeff Yates