2013-06-17 4 views
0

Я пробовал много разных вещей и не могу заставить этот код работать. Мой код, чтобы остановить backgroundworker, затем закрыть окно.Close form after stoppping background worker not working

protected override void OnFormClosing(FormClosingEventArgs e) 
    { 
     if (bw.IsBusy) 
     { 
      bw.CancelAsync(); 
      e.Cancel = true; 
      MessageBox.Show("close"); //Does show 
      return; 
     } 
     base.OnFormClosing(e); 
    } 

Во время м.т. рабочего

if (worker.CancellationPending) 
     { 
      MessageBox.Show("Cancel"); // Does not show 
      //Cancel 
      e.Cancel = true; 
     } 

На завершенного фоне рабочего

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     MessageBox.Show("Completed"); //Does not work 

     //Check if restart 
     if (bw_restart) 
     { 
      bw_restart = false; 
      bw.RunWorkerAsync(); 

     } 
     //If it was cancelled 
     if (e.Cancelled) 
     { 
      this.Close(); 
     } 
     //If error show error message 
     else if (e.Error != null) 
     { 
      MessageBox.Show(e.Error.ToString()); // Does not show 
     } 
     else //No errors or cancelled 
     { 
      MessageBox.Show(e.ToString()); //Does not shoiw 
     } 

    } 

Отменить кнопку

private void cancel_Click(object sender, EventArgs e) 
    { 
     bw.CancelAsync(); //Does not work :s 
    } 

Это не закрывает окно, в X при нажатии не что-нибудь, я получил он закрывает форму, но не останавливает фонового работника, меня немного смущает. Ссылка на код, который я получил по этой проблеме, которая не работает: How to stop BackgroundWorker on Form's Closing event?

+0

не используйте 'this.Close()', попробуйте использовать 'this.DialogResult = DialogResult.Cancel' вместо этого. (если это работает, я напишу в качестве ответа) – Sayse

+1

В связанном ответе Ханса Пассана он не проверяет e.cancelled в RunWorkerCompleted-Function. Может, это проблема? –

+1

Отладка программы. Посмотрите, будет ли выполняться обработчик BGW, если 'e.Cancelled' истинно. Затем посмотрите, что такое значение 'mClosePending'. Вы уверены, что 'this.Close' вызывается, когда BGW закончен? Если да, поставьте точку останова в обработчике события закрытия окна и посмотрите, снова ли он попал (и если да, то что он делает). – Servy

ответ

1

Как указано в моем комментарии, ваш BackgroundWorker закончился из-за ошибки, попробуйте добавить следующее вверху вашего рабочего рабочего. Как только эта ошибка будет решена, ваш вопрос будет более ответственным.

if(e.Error != null) 
    MessageBox.Show(e.Error.toString());//Put a breakpoint here also 
+0

Я обновил код, кажется, что e.cancel не работает. – user1977434

+0

@ user1977434 - Работает ли фоновый рабочий? что такое значение bw_restarts? вы должны использовать точки останова вместо Messagebox.Show, есть много учебников о том, как это сделать – Sayse

2
if (e.Cancelled) 

Это в корне неправильно. Вы никогда не сможете быть на 100% уверены, что он будет установлен. Отмена BGW всегда является условием гонки, BGW, возможно, был занят выходом, когда вы назвали метод CancelAsync(), поэтому никогда не видел, чтобы значение параметра CancellationPending равнялось true, поэтому никогда не назначалось e.Cancel = true в обработчике событий DoWork.

Все, что вам известно, это факт, что mClosePending является надежным, так как он установлен на true в потоке пользовательского интерфейса. Поэтому всегда вызывайте Close(), оно равно true, независимо от состояния e.Cancelled.

И да, проверка e.Error также не повредит. Но еще проверить mClosePending.

+0

Я обновил код, кажется, что e.cancel не работает. – user1977434

+0

Недостаточно фрагмента кода, я не вижу точно, где находится тест отмены. Помещение его в начале обработчика событий DoWork является распространенной ошибкой. Но это не было моим ответом, дело в том, что вы не должны проверять e.Cancelled, потому что это ненадежно. –

0

CancelAsync фактически не прерывает вашу нить или что-то в этом роде. Он отправляет сообщение в рабочий поток, что работа должна быть отменена с помощью BackgroundWorker.CancellationPending. Ваш делегат DoWork, который запускается в фоновом режиме, должен периодически проверять это свойство и обрабатывать отмену.

Посмотрите на это:

private BackgroundWorker background; 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     background = new BackgroundWorker(); 
     background.WorkerSupportsCancellation = true; 
     background.DoWork += BackgroundOnDoWork; 
     background.RunWorkerCompleted += BackgroundOnRunWorkerCompleted; 

     background.RunWorkerAsync(); 
    } 

    private void BackgroundOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs) 
    { 
     MessageBox.Show("stop"); 
    } 

    private void BackgroundOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs) 
    { 
     // your doWork loop should check if someone don't call background.CancelAsync(); 
     while (!background.CancellationPending) 
     { 
      // do something 
     } 
    } 

    private void ButtonClick(object sender, EventArgs e) 
    { 
     background.CancelAsync(); 
    } 
+0

Проверка параметра в вашем цикле while не будет работать. Значения параметров не изменяются. Вероятно, это должно выглядеть примерно так: 'while (! Background.CancellationPending)' – LarsTech

+0

да, конечно. Я изменил это. Я также добавляю 'background.WorkerSupportsCancellation = true;' - без него нельзя вызвать 'cancelAsync' – nirmus