BackgroundWorker завершает работу перед DoWork

2

Я использую фона рабочего для обработки загрузки файла, чтобы остановить мой ui от замораживания, однако кажется, что RunWorkerCompleted заканчивается до завершения моего события DoWork (вызывает ошибки при выходе из диалога). Я что-то делаю неправильно? Мне лучше делать это над заданием?

public static <T> LoadDesign(string xmlPath)
{
    PleaseWait pw = new PleaseWait(xmlPath);
    pw.ShowDialog();
    return pw.design;
}


private PleaseWait(string xmlFile)
{
   InitializeComponent();
   bw = new BackgroundWorker();
   bw.WorkerSupportsCancellation = true;
   bw.DoWork += (s, e) =>
   {
      design = (Cast)DllCall containing XmlSerializer.Deserialize(...,xmlFile);
   };
   bw.RunWorkerCompleted += (s, e) => {
   //Exit please wait dialog
      this.Close(); 
   };
   if (!bw.IsBusy)
       bw.RunWorkerAsync();
}

Я считаю, что проблема может быть связана с тем, что мой фоновый работник вызывает DLL и не ждет ответа. Я попытался добавить проверки, такие как while(design == null), безрезультатно..

Edit2 Ошибка NRE по мере того, как проект не был загружен, я могу легко исправить это, но вместо этого вместо этого будет работать поток.

  • 0
    Если вы хотите получить ответ, предоставьте полную информацию об основном коде. Это (cast) DllCall слишком много псевдокода.
  • 0
    @HenkHolterman - я добавил метод, но не понимаю, насколько он актуален? (также в процессе добавления Using to dll )
Показать ещё 7 комментариев
Теги:
winforms
backgroundworker

2 ответа

3
Лучший ответ

Есть много маленьких ошибок. Учитывая, что мы, вероятно, не смотрим на реальный код и что у нас нет отладчика с окном Call Stack, чтобы увидеть, где он фактически выйдет из строя, любой из них может быть фактором.

  • Тестирование bw.IsBusy и не запуск рабочего, когда оно истинно, является серьезной ошибкой. Он никогда не может быть занят в коде как отправленный, но если это действительно возможно, чтобы он был правдой, тогда у вас есть неприятная ошибка в коде. Поскольку вы действительно подписали события на занятого рабочего. Теперь обработчик события RunWorkerCompleted будет выполняться дважды.

  • Использование метода Close() для закрытия диалогового окна неверно. Диалог должен быть закрыт, назначив его свойство DialogResult. Однако не самая грубая ошибка, но тем не менее неправильная.

  • Там будет раса в коде, рабочий может завершить до появления диалога. Диалоговое окно можно закрыть только при создании собственного окна. Другими словами, IsHandleCreated должен быть правдой. Вы должны заблокировать это, чтобы этого никогда не было. Подпишите диалоговое окно "Загрузить событие", чтобы запустить рабочий.

  • Слепо предположить, что работник закончит работу и произведет результат. Это не так, если его метод DoWork умер от исключения. Который пойман BackgroundWorker и передан обработчику события RunWorkerCompleted как свойство e.Error. Вы должны проверить это свойство и сделать что-то разумное, если оно не пустое.

Судя по комментариям, я бы предположил, что последняя пуля является причиной. Вы отлаживаете это с помощью Debug + Exceptions, установите флажок "Бросок" для исключений CLR. Отладчик теперь остановится, когда будет выбрано исключение, что позволит вам узнать, что пошло не так.

  • 0
    Спасибо, Ганс, ты действительно был прав насчет моих слепых предположений. Я ожидал бы, что эта ошибка была брошена все же? Кроме того, есть ли у вас какие-либо ссылки на то, почему я должен использовать DialogResult? Я заинтригован...
  • 0
    Исключение, безусловно, выброшено. И пойман, так что он может быть передан в обработчик событий RunWorkerCompleted. Это был намеренный дизайн, BGW не был бы настолько популярен, если бы он часто ломал программы. Я бы порекомендовал любую книгу о программировании Winforms, чтобы узнать больше о диалогах. Есть много хороших доступных. Или просто нажмите кнопку Задать вопрос.
1

Возможно, ваш фоновый рабочий на самом деле не займет много времени и не завершится до того, как появится диалог. Я бы предложил сдвинуть инициализацию рабочего фона и запустить код до PleaseWait Form_Load или Form_Shown

  • 1
    Я бы даже сдвинул его на Shown , так как это событие вызывается при отображении формы. Load может быть вызвана задолго до Shown .
  • 0
    Да, согласен с вами - обновил мой ответ одновременно.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню