Need help to stop the BackgroundWorker thread
Need help to stop the BackgroundWorker thread. I am trying to stop a background worker thread. This is what I am doing:
On stop button click (UI layer):
if (backgroundWorker.IsBusy == true &&
backgroundWorker.WorkerSupportsCancellation == true)
{
backgroundWorker.CancelAsync();
}
On DoWork event (UI layer):
if ((backgroundWorker.CancellationPending == true))
{
e.Cancel = true;
}
else
{
//Function which progresses the progress bar is called
//here with its definition in business layer
}
Once the DoWork eve开发者_如何转开发nt is fired and my program control is in the function defined in Business layer, how do I revert back to the DoWork event to set ‘e.Cancel = true’?
Setting e.Cancel does nothing, if CancellationPending is true you need to basically break out of DoWork() using return or whatever (after you've stopped what you're doing).
Something like:
private void DoWork(...)
{
// An infinite loop of work!
while (true)
{
// If set to cancel, break the loop
if (worker.CancellationPending)
break;
// Sleep for a bit (do work)
Thread.Sleep(100);
}
}
DoWork() executes in a seperate thread to the UI thread, you can report back to the UI thread using BackgroundWorkr.ReportProgress().
DoWork
will run in it's own thread and is not dependant of the GUI thread.
You do almost everything correct. From the GUI thread, set the CancellationPending
to true
.
In the DoWork
method, you probably have a loop of some sort.
Here you check if CancellationPending == true
, but in addition to setting e.Cancel
to true, also include a return
call to make the method return and effectively stopping the worker. This also causes the WorkerCompleted event to fire on the GUI thread if the method is hooked up.
If the DoWork
method perform some long task that is not divided into parts (for example if your DoWork
method looks like this:
void DoWork( (object sender, DoWorkEventArgs e)
{
myClass.SomeLongOperation();
}
Then you are out of luck, since you need to manually check the CancellationPending
inside the DoWork
method to be able to stop it. If the DoWork
itself "hangs" and waits for a operation you can't control, you can't stop it (in any orderly fashion) by setting CancellationPending
from the GUI thread.
Once the DoWork event is fired and my program control is in the function defined in Business layer, how do I revert back to the DoWork event to set ‘e.Cancel = true’?
You don't. If you want cancellation to be possible during execution of your business layer, then your business layer must support cancellation. So, you have two options:
- In your DoWork method, call only short-time business layer methods and check for CancellationPending in between.
- Make your business layer methods cancellation-aware, i.e., pass the BackgroundWorker to them and have them periodically check CancellationPending (and retun, once it turns true).
Keep checking the CancellationPending=True Flag in the else part of your logic, and return when true.
The code e.Cancel = true
only sets a state on the BackgroundWorker, so that it knows it has been cancelled, it doesn't actually cancel the process.
You'll have to check the CancellationPending
inside the loop of your method and break
it or return
.
void DoWork(object sender, DoWorkEventArgs e) {
for (int i = 0; i < length; i++) {
if(e.CancellationPending) {
return;
}
// Long running code
}
}
精彩评论