Kill BackgroundWorker Thread

mskeel

Senior Contributor
Joined
Oct 30, 2003
Messages
913
VB .Net 2.0 question.

I'm using the BackgroundWorker Component on a form. Everything works great, except for updating the status strup progress bar and canceling all work in the background worker thread. Basically, I want to kill all thread operations when the user clicks a cancel button. Accouding to the API, the best that the BackgroundWorker has is a RequestCancel which then flips a boolean (CancellationPending) to true. It is then up to the user to determine what action to take. From hunting the web, the best I can tell is that the intended action is to check if the thread has been cancelled and then ignore updates and let the thread terminate on it's own. Something like this:
Visual Basic:
    Private Sub ExecutePlugins(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles _worker.DoWork
       '
       ' Kick off Time consuming process
       '
    End Sub
    '
    Private Sub ProcessUpdate(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles _worker.ProgressChanged
         If Not Me._worker.CancellationPending Then
            '               
            ' update the status for the user
            '
         End If
    End Sub
    '
    Private Sub ExecutionCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles _worker.RunWorkerCompleted
         '
         ' Clean everything up becuase you're done.
         '
    End Sub
While that's fine and dandy for something like a database query where you're sucking CPU time on somebody else's computer, I'm doing extremely intense operations on my machine. If I press cancel, it's becuase I need the operations to cease, not stop showing me the updates. If the thread keeps hogging CPU cycles then I can't get work done and I certianly can't fix whatever was wrong and then crank up a new thread. I'm pretty sure that if I throw an unhandled exception in the worker thread then the thread will instantly terminate. That sounds really hacky and I'm not too confident that it will actually get everything to stop.

What is the best way to kill a BackgroundWorker immediatly?
 
I don't see any RequestCancel method. I just see a CancelAsync method, and that seems to cancel the backrgound work without any problems.
 
What if within in the thread that you want to cancel you check the System.Threading.Thread.CurrentThread.ThreadState property and if it returns ThreadState.AbortRequested abort the operation and clean up resources. I don't really know if this will work but it is worth a shot. It only makes sense to me that if a thread is to be aborted it must be done internally within that thread so that it can do things cleanly (i.e. free resources/update external/static objects).
 
Never mind. BackgroundWorker.CancelAsync has no effect on the ThreadState property. I know that there is little documentation on BackgroundWorker on MSDN installed with VS, but I went online and searched MSDN and found that
When you call CancelAsync, your worker method has an opportunity to stop its execution and exit. The worker code should periodically check the CancellationPending property to see if it has been set to true.
It is still up to your background thread to cancel the operation itself, though.
 
Right, marble_eater, you have discovered the crutch of the problem. The only way to terminate is to check the thread every once in a while to ensure you should still be cranking and exit if you aren't.

That's great if you have control over the execution, but say you make a blocking call to a function in another library that takes a long time to execute. This method doesn't know anything about the background worker thread, how to check for a cancellation pending, or anything else -- so even when the user requests a cancel, the method just keeps on blocking, doing whatever it was that it was doing.

I think the best solution in this case, assuming you have control over the interface of the class in which this blocking method resides, is to create an event of some kind (maybe CancelRequest or something like that) so that you can cleanly pass on the cancellation request to the blocking method (which would still have to check occasionally and decide whether or not to honor the request).

What if I don't want to politely request? What if I want to kill the thread immediately? I guess there is an issue with that where resources won't necessarily be cleaned up by the blocking method...so maybe it really doesn't make sense to do immediately kill the thread at all?
 
Sorry, I guess I didn't read your original post very thouroughly.

It is unfortunate if the code you are calling is beyond your control, but it is always a possibility, I suppose. You can try to immediately terminate the thread using the System.Threading.Thread class. If you want to do things a little more neatly the only other option I can come up with is to set the thread's priority to Lowest (if it isn't already), allow it to terminate on its own, and hope that it doesn't steal too many CPU cycles. If the thread is simply blocking it shouldn't be eating up the CPU cycles, but if the operation is CPU intensive then I guess you're just stuck between a rock and a hard place.
 
Before I go any further, is it necessary to terminate things more neatly? If whatever is going on in the background process has allocated memory and I terminate the thread with a hard kill, what happens to that allocated memory? Will it be considered ready for collection by the GC or will it be the source of a memory leak?
 
It will not cause a memory leak. The only way to cause a memory leak is to forget to release references to large numbers of objects. On a collection the GC will still see the allocated objects and see that they are or are not referenced. The problem is that certain tasks do not get completed where the code had inticipated that they would. For instance, objects won't dispose and certain variables might not be updated properly. If there is an object using unmanaged resources, such as memory or open files, those objects could end up going undisposed until they are collected by the garbage collector.
 
Memory leak...heh. I didn't think that one through all the way. It's rough to transition between languages sometimes. Really, I guess a dangling file handle is the most dangerous problem I face (where a file might become locked preventing others from using it because a writer was never closed).

Anyway, I'll see if I can kill the background worker thread with something in the thread class. Thanks for your help and ideas.
 
Back
Top