问题
My app uses background worker to go do some work inside a loop. I have it so that at each loop iteration, it checks if cancellation pending is true and if it is, breaks out the loop. All OK, my app stops processing once it is finished the current iteration of the loop. The problem is that I think the background worker is still running - if I click the button to start processing again, I get an error saying the background worker is busy.
I was going to dispose of the worker but then it is created when the form runs and so if I dispose of it, it is not there to start doing work again. What I really want to do is tell the background worker that it is complete, if I click a 'stop processing' button, so it is ready to start processing again when I click the start button!
I was going to try this:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (!backgroundWorker1.CancellationPending)
{
// Start processing in a background thread so the GUI remains responsive,
// pass in the name of the text file produced by
// PFDR FilenameLogic(txtLetterType.Text);
}
}
回答1:
Same answer as Marc Gravell but you don't seem to follow.
Are you setting e.cancel = true?
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; i <= 10; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
worker.ReportProgress(i * 10);
}
}
}
回答2:
When you create the worker, set worker.WorkerSupportsCancellation
to true
. Now inside the DoWork
handler, you must periodically (most commonly, at the start of some loop, etc) check for worker.CancellationPending
- if it is true, set e.Cancel = true;
(so that you can distinguish completion from cancellation), clean-up, and exit (return;
). Now your cancel button can invoke worker.CancelAsync();
and it will act appropriately.
回答3:
I hardly found a nice way how to cancel a Backgroundworker over a Stop Button:
My App looks like this, two buttons and one progressbar:
After pressed Stop Button it looks like this:
For the Start button click method, the code checks if the BGW is busy. If not Start the BGW:
private void btnStart_Click(object sender, EventArgs e)
{
//BGW
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
}
The stop button calls the following method, which sets a flag, CancellationPending to true:
private void btnStop_Click(object sender, EventArgs e)
{
backgroundWorker1.CancelAsync();
}
This flag can be used in the backgroundWorker1_DoWork method, which is responsible for processing high time consuming functions:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 100; i++)
{
backgroundWorker1.ReportProgress(i);
Thread.Sleep(100);
if (backgroundWorker1.CancellationPending && backgroundWorker1.IsBusy)
{
e.Cancel = true;
return;
}
}
}
And now comes the tricky part, because before closing the extra thread, you have to check the e object in the backgroundWorker1_ProgressChanged if it is cancelled or not!!!!! OTHERWISE you will get an Error.
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
int i = 0;
if (!e.Cancelled)
{
i = (int)(e.Result);
}
else
{
i = 0;
}
// Check to see if an error occurred in the
// background process.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
return;
}
// Check to see if the background process was cancelled.
if (e.Cancelled)
{
MessageBox.Show("Processing cancelled.");
return;
}
// Everything completed normally.
// process the response using e.Result
MessageBox.Show("Processing is complete.");
}
Extra information: Dont forget to set these Backgroundworker flags:
//Set WorkerReportsProgress true - otherwise no ProgressChanged active
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
If this tiny tutorial was helpful --> Thumb up
回答4:
I seem to have solved the error - in the Backgroundworker DoWork method I put in a while CancelPending is not true and when it is true I set e.Cancel = true It now seems to work fine!
来源:https://stackoverflow.com/questions/16057022/stopping-background-worker