BackgroundWorker RunWorkerCompleted в компоненте - PullRequest
0 голосов
/ 01 июня 2010

Я знаком со следующим:

"Если операция вызывает исключение, которое ваш код не обрабатывает, BackgroundWorker перехватывает исключение и передает его в обработчик события RunWorkerCompleted, где оно отображается как свойство Error System.ComponentModel.RunWorkerCompletedEventArgs. Если вы выполняете в отладчике Visual Studio отладчик прерывается в той точке обработчика событий DoWork, где возникло необработанное исключение. "

Однако я столкнулся со странным сбоем.

В моем компоненте есть экземпляр BackgroundWorker.

Даже если он не запущен в отладчике, исключение остается необработанным работником.

Даже упрощенный код создает необработанное исключение (а RunWorkerCompleted не запускается):

Throw New ArgumentException("Test")

Главное - это код RunWorkerComplete:

RaiseEvent UpdateComplete(Me, New AsyncCompletedEventArgs(e.Error, e.Cancelled, e.Result))

Мне нужен компонент для предоставления исключения работника через публичное событие.

Если я удаляю вызов RaiseEvent, исключение становится обработчиком работника и доступно через e.Error.

По-видимому, возбуждение события заставляет работника пропустить исключение. Как это может быть?

Полный код:

Компонент:

Private Sub workerDownloader_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)

        RaiseEvent UpdateComplete(Me, New AsyncCompletedEventArgs(e.Error, e.Cancelled, e.Result))

End Sub

Private Sub workerDownloader_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
        Throw New ArgumentException("Test")
End Sub

Хост-приложение (WinForms):

Private Sub Connector1_UpdateComplete(ByVal sender As System.Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) Handles Connector1.UpdateComplete
        If e.Error IsNot Nothing Then MessageBox.Show(e.Error.ToString)
End Sub

Ответы [ 2 ]

2 голосов
/ 01 июня 2010

Возможно, ваш e.Result выдал свое собственное исключение.

С документация MSDN на RunWorkerCompletedEventArgs:

Ваше RunWorkerCompleted событие Обработчик всегда должен проверять Error и Cancelled свойства до доступа к Result имущество. Если возникло исключение или если операция была отменена, доступ к собственности Result поднимает исключение.

В частности, он поднимет TargetInvocationException.

В коде, который вы опубликовали, вы создаете новый объект AsyncCompletedEventArgs из аргумента, переданного через ваше событие RunWorkerCompleted. Я не уверен, каково ваше обоснование для этого, но me выглядит как ненужный шаг, поскольку RunWorkerCompletedEventArgs наследует от AsyncCompletedEventArgs - и поэтому вы можете просто передать свой e (RunWorkerCompletedEventArgs объект) на ваше UpdateComplete событие:

Private Sub workerDownloader_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        RaiseEvent UpdateComplete(Me, e)
End Sub

Теперь, вот почему это может решить вашу проблему (и почему ссылка на MSDN, которую я разместил, актуальна): то, как вы в настоящее время делаете это, вы получаете доступ к e.Result при вызове конструктор для AsyncCompletedEventArgs. Получив доступ к свойству там, перед первой проверкой e.Error вы создаете сценарий, в котором выдается исключение в процессе оценки параметров, передаваемых в UpdateComplete. Из-за этого исключения ваша строка RaiseEvent не может завершить то, что она делает; следовательно, ваше UpdateComplete событие не вызывается.

1 голос
/ 01 июня 2010

Обновление на основе ваших обновлений вопроса ... Я смоделировал это в коде C #, и похоже, что это (перекрестная нить?) Проблема, пытающаяся передать Result из аргументов события в AsyncCompletedEventArgs.

Передача ошибки и отмена работает, но когда я пытаюсь передать объект результата, он умирает.Вам нужен объект результата в событии?

UpdateComplete(this, new AsyncCompletedEventArgs(e.Error, e.Cancelled, null));
...