Ho un BackgroundWorker che esegue un singolo processo. Voglio essere in grado di annullare l'elaborazione mentre sta andando, ma quando chiamo il metodo CancelAsync(), in realtà non annulla mai. Dove mi sbaglio?Backgroundworker.CancelAsync() non funziona
Ecco il metodo DoWork():
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker b = sender as BackgroundWorker;
if (b != null)
{
if (!b.CancellationPending)
{
try
{
// Let's run the process as a backgroundworker so we have the ability to cancel the search, and/or be able to view results while it's still searching
ProcessParameters pp = e.Argument as ProcessParameters;
if (pp.DoReplace)
results = FindReplace.FindReplace.FindAndReplace(pp.PathToSearch, pp.FindText, pp.ReplaceText, pp.UseRegularExpressions, pp.IncludeList, pp.ExcludeList, pp.RecurseSubdirectories, pp.IgnoreCase);
else
results = FindReplace.FindReplace.Find(pp.PathToSearch, pp.FindText, pp.UseRegularExpressions, pp.IncludeList, pp.ExcludeList, pp.RecurseSubdirectories, pp.IgnoreCase);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
else
{
// Cancel was clicked
e.Cancel = true;
}
}
}
Ecco il metodo che inizia il trattamento:
private void btnGo_Click(object sender, EventArgs e)
{
if (btnGo.Text == "Cancel")
{
if (DialogResult.Yes == MessageBox.Show("Are you sure you wish to cancel?", "Cancel Requested", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
bgw.CancelAsync();
return;
}
if (tbFind.Text.Length == 0)
{
MessageBox.Show("Find text is not valid.");
return;
}
tbFound.Text = String.Empty;
tbFoundInThisFile.Text = String.Empty;
lvResults.Items.Clear();
includeList = null;
excludeList = null;
results = null;
if (radDirectory.Checked && !radFile.Checked)
{
includeList = BuildIncludeExcludeList(tbIncludeFiles.Text);
excludeList = BuildIncludeExcludeList(tbExcludeFiles.Text);
}
ProcessParameters pp = null;
if (chkReplace.Checked)
pp = new ProcessParameters(tbPath.Text, tbFind.Text, tbReplace.Text, chkUseRegEx.Checked, includeList, excludeList, chkRecursion.Checked, chkIgnoreCase.Checked, true);
else
pp = new ProcessParameters(tbPath.Text, tbFind.Text, chkUseRegEx.Checked, includeList, excludeList, chkRecursion.Checked, chkIgnoreCase.Checked, false);
bgw.RunWorkerAsync(pp);
// Toggle fields to locked while it's running
btnGo.Text = "Cancel";
}
Ed ecco la WorkerCompleted() evento:
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnGo.Text = "Go";
string message = String.Empty;
const string caption = "FindAndReplace is Complete";
if (!e.Cancelled)
{
if (results != null)
{
tbFound.Text = results.Found.ToString();
tbSearched.Text = results.FilesSearched.ToString();
tbSkipped.Text = results.FilesSkipped.ToString();
message = String.Format("Search finished resulting in {0} match(es).", results.Found);
}
else
message = "The FindAndReplace results were empty. The process was cancelled or there was an error during operation.";
}
else
message = "The FindAndReplace process was cancelled.";
if (e.Error != null)
message += String.Format("{0}{0}There was an error during processing: {1}", Environment.NewLine, e.Error);
MessageBox.Show(message, caption);
}
hai solo una piccola finestra che controlla CancellationPending. Non lo riscalderai. –
OT ma nel tuo Gestore completato il controllo per e.Error dovrebbe essere il primo. –