Почему моя программа выполняется после того, как я отменил BackgroundWorker? - PullRequest
2 голосов
/ 20 февраля 2020

Я практикую использование BackgroundWorker для выполнения некоторых трудоемких работ. Моя цель - показать все пути к файлам в пользовательском интерфейсе.

enter image description here

Я нажимаю кнопку RUN и нажимаю кнопку CANCEL после выполнения в течение 5 секунд. Это работает нормально.

Затем я повторяю вышеупомянутые шаги, я замечаю, что "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);
  }
}

1 Ответ

2 голосов
/ 20 февраля 2020

Каждый раз, когда вы нажимаете кнопку, вы добавляете событие в работника.

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 запускается снова (на этот раз с двумя событиями), и в общей сложности три запуска.

Вы должны настроить работника где-то еще.

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

Как Шоки упомянул в комментариях, Вы также можете удалить существующее событие, прежде чем присоединить новое.

...