为什么取消BackgroundWorker后我的程序就执行了?

Why my program executed after I cancel BackgroundWorker?

正在练习使用BackgroundWorker做一些比较耗时的工作。 我的目标是显示 UI.

上的所有文件路径

我按运行键,执行5秒后按取消键。它工作正常。

然后我重复上面的步骤,我注意到"Check_File"第三次执行了。

我觉得应该只有两次。

UI 显示如下:

  1. Searching for Files → Many FileName Appear → Canceled

  2. Searching for Files → Many FileName Appear → Searching for Files → Canceled

以下是我的代码:

private void Run_Click(object sender, RoutedEventArgs e)
{
  worker.WorkerSupportsCancellation = true;
  worker.WorkerReportsProgress = true;
  worker.DoWork += Worker_DoWork;
  worker.ProgressChanged += Worker_ProgressChanged;
  worker.RunWorkerAsync(PText.Text);
  worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
}

private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  if (e.Cancelled == true)
  {
    FLabel.Content = "Canceled";
  }
  else
  {
    FLabel.Content = "Finish";
  }

  worker.Dispose();
}

private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
  FLabel.Content = e.UserState.ToString();
}

private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
  Check_File("My_Folder_Path", (String)e.Argument, e);
}

private void Cancel_Click(object sender, RoutedEventArgs e)
{
  worker.CancelAsync();
}

public void Check_File(string Path, string FindStr, DoWorkEventArgs e)
{
  string v_alert;

  i += 1;

  try
  {
    if (Path.LastIndexOf('\') != Path.Length)
    {
      Path = string.Concat(Path, "\");
    }

    if (Directory.Exists(Path))
    {
      worker.ReportProgress(0, string.Concat("Searching for Files...", i.ToString()));

      string[] Files = Directory.GetFiles(Path);

      if (Files.Length != 0)
      {
        foreach (string f in Files)
        {
          if (worker.CancellationPending == true)
          {
            e.Cancel = true;
            break;
          }

          worker.ReportProgress(Array.IndexOf(Files, f) / Files.Length * 100, f);
        }
      }
    }
    else
    {
      v_alert = string.Concat("No Path:", Path);
      MessageBox.Show(v_alert);
    }
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
}

每次按下按钮时,都会向工作人员添加一个事件。

private void Run_Click(object sender, RoutedEventArgs e)
{
    worker.WorkerSupportsCancellation = true;
    worker.WorkerReportsProgress = true;
    worker.DoWork += Worker_DoWork;                         //<----Happens here
    worker.ProgressChanged += Worker_ProgressChanged;
    worker.RunWorkerAsync(PText.Text);
    worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
}

所以如果你按一次。工作人员附加了一个事件。如果你再按一次,工人会得到另一个事件。他现在有两个事件。他又跑了一次(这次有 2 个项目),总共跑了 3 次。

您应该在其他地方设置工作器。

public Form1()
{
    InitializeComponent();

    //Init the worker here...
    worker.WorkerSupportsCancellation = true;
    worker.WorkerReportsProgress = true;
    worker.DoWork += Worker_DoWork;
    worker.ProgressChanged += Worker_ProgressChanged;
    worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
}

private void Run_Click(object sender, RoutedEventArgs e)
{
    //only run the worker here
    worker.RunWorkerAsync(PText.Text);       
}

正如 Shocky 在评论中提到的,您还可以在附加新事件之前删除现有事件。