wpf отменить фоновый работник при выходе из приложения - PullRequest
2 голосов
/ 26 марта 2010

В моем приложении у меня есть главное окно, и в него я загружаю страницу. Эта страница выполняет долгое время, когда пользователь нажимает кнопку. Моя проблема в том, что, когда выполняется длинная задача, и пользователь нажимает кнопку закрытия главного окна, приложение, похоже, не завершает работу, потому что я отлаживаю его в VS2008 и вижу, что кнопка остановки подсвечена. Если я хочу закончить, я должен нажать кнопку «Стоп», приложение не останавливает отладку автоматически при выходе из приложения. Я думал, что .NET автоматически останавливает фоновых рабочих при выходе из приложения, но я не уверен, увидев это поведение. Я пытался заставить и отменить фонового работника на странице незагруженных событий примерно так:

    private void Page_Unloaded(object sender, RoutedEventArgs e)
    {
        // Is the Background Worker do some work?
        if (My_BgWorker != null && My_BgWorker.IsBusy)
        {
            //If it supports cancellation, Cancel It
            if (My_BgWorker.WorkerSupportsCancellation)
            {
                // Tell the Background Worker to stop working.
                My_BgWorker.CancelAsync();
            }
        }


    }

но безуспешно. После выполнения функции CancelAsync () через несколько минут я вижу, как фоновый работник завершает работу, и вызывает RunWorkerCompleted, и я вижу, что задача завершена, проверяя аргумент e.Cancelled в событии, но после этого события приложение продолжает работу без выхода, и понятия не имею, что делает ....

Я установил для WorkerSupportsCancellation значение true, чтобы поддержать отмену в начале.

Я бы оценил все ответы. Спасибо.

Ответы [ 3 ]

4 голосов
/ 26 марта 2010

Отмена не автоматическая, ваш код в обработчике события DoWork должен обработать отмену путем проверки значения свойства CancellationPending Вызов CancelAsync не прерывает поток, он просто устанавливает CancellationPending в true ...

Например:

private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    while(!bgw.CancellationPending)
    {
        ...
    }
}
0 голосов
/ 29 марта 2010

Идеальный Томас, установка ShutdownMode на OnMainWindowClose, как вы сказали, решила мою проблему. Теперь отладчик останавливается правильно;) Большое спасибо за помощь.

То, что я сделал, это:

       <Application 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                        
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         x:Class="GParts.App"
         StartupUri="WinMain.xaml"
         ShutdownMode="OnMainWindowClose">

                   <...>

        </Application>

Наконец, я хотел бы сделать одно замечание по отношению к backgroundworker в событии DoWork в случае, если исключение вызвано каким-либо типом ошибки: я передаю ошибки внутри него с помощью предложения try catch и в catch, который я делаю:

        catch (Exception ex)
        {
            e.Result = ex.Message;               
        }

Когда backgroundworker завершает работу по исключению, я хочу в RunWorkerCompleted обнаружить его с помощью e.Error и показать его. Итак, что я делаю в RunWorkerCompleted:

        if (e.Cancelled)
        {
            // Cancelled

        }
        else if (e.Error != null)
        {
            // Exception Thrown
            // Here I want to show the message that produced the exception in DoWork
            // event. If I set  e.Result = ex.Message in DoWork event, is e.Error here
            // containing ex.Message?


        }
        else
        {
            // Completed);
        }

Является ли e.Error в RunWorkerCompleted содержащим ex.Message?

Спасибо.

0 голосов
/ 26 марта 2010

Я думаю, что Томас Левеск определил проблему.

На заметку общего характера: где-то какой-то поток все еще выполняется. Вы можете попытаться выяснить, что это за поток, приостановив процесс отладки (кнопка паузы с именем «Break All»). На этом этапе следующая выполненная строка кода должна быть выделена. Кроме того, вы можете использовать окно «Потоки» (в разделе «Отладка -> Windows»), чтобы точно определить, какой поток все еще работает и где.

...