【问题标题】:Why my program executed after I cancel BackgroundWorker?为什么我的程序在我取消 BackgroundWorker 后执行?
【发布时间】:2020-02-20 07:44:14
【问题描述】:

我正在练习使用 BackgroundWorker 来做一些耗时的工作。 我的目标是在 UI 上显示所有文件路径。

我按下 RUN 按钮并在执行 5 秒后按下 CANCEL 按钮。它工作正常。

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

我认为应该只有两次。

界面如下图:

  1. 正在搜索文件 → 出现许多文件名 → 已取消

  2. 正在搜索文件 → 出现许多文件名 → 正在搜索文件 → 已取消

以下是我的代码:

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);
  }
}

【问题讨论】:

  • 如何验证CheckFile 被调用了3次?
  • 在您的点击事件中添加 Do-Work。每次点击都会发生这种情况。
  • 我猜你在点击按钮时调用Run_Click,每次按下它你都会在你的工作中添加另一个事件(例如 DoWork ),所以当你第一次有一个事件时,在第二次单击时,您有 2 个,因此它将执行您通过该函数的次数,使用 if(worker == null) 扭曲它
  • @LarsKristensen 我加“i”来计算它执行了多少次

标签: c# wpf backgroundworker


【解决方案1】:

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

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;
}

所以如果你按一次。工作人员附加了一个事件。如果您第二次按下它,工作人员会附加另一个事件。他现在有两个事件。 Hes 再次运行(这次有 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 在 cmets 中提到的,您还可以在附加新事件之前删除现有事件。

【讨论】:

  • 或在使用-= 分配事件代表之前删除它们,例如worker.DoWork -= Worker_DoWork;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多