Нужен второй (и третий) ) мнения о моем исправлении для этого состояния гонки Winforms

В блогах и т. д. есть сотни примеров того, как реализовать фонового рабочего, который регистрирует или сообщает статус переднему элементу GUI. Большинство из них включают подход к обработке состояния гонки, которое существует между порождением рабочего потока и созданием диалогового окна переднего плана с помощью ShowDialog (). Однако мне пришло в голову, что простой подход состоит в том, чтобы принудительно создать дескриптор в конструкторе формы, чтобы поток не смог инициировать вызов Invoke / BeginInvoke в форме до создания своего дескриптора.

Рассмотрим простой пример класса Logger, который использует фоновый рабочий поток для входа на передний план.

Предположим также, что мы не хотим, чтобы NLog или какой-либо другой тяжелый фреймворк делал что-то настолько простое и легкое.

] Окно моего регистратора открывается с помощью ShowDialog () потоком переднего плана, но только после запуска фонового «рабочего» потока. Рабочий поток вызывает logger.Log (), который сам использует logForm.BeginInvoke () для правильного обновления элемента управления журналом в потоке переднего плана.

  public override void Log(string s)
  {
     form.BeginInvoke(logDelegate, s);
  }

Где logDelegate - это просто простая оболочка вокруг «form.Log ()» или другого кода это может обновить индикатор выполнения.

Проблема заключается в существующем состоянии гонки; когда фоновый рабочий поток начинает вести журнал до того, как вызывается ShowDialog () переднего плана, дескриптор формы еще не создан, поэтому вызов BeginInvoke () завершается сбоем.

Я знаком с различными подходами, включая использование события Form OnLoad и таймер для создания рабочей задачи, приостановленной до тех пор, пока событие OnLoad не сгенерирует сообщение таймера, которое запускает задачу после отображения формы или, как упоминалось, с использованием очереди для сообщений. Однако я думаю, что простое принудительное создание дескриптора диалогового окна на раннем этапе (в конструкторе) гарантирует отсутствие состояния гонки, предполагая, что поток порождается тем же потоком, который создает диалоговое окно.

http://msdn.microsoft .com / en-us / library / system.windows.forms.control.handle (v = vs.71) .aspx

MSDN сообщает: «Если дескриптор еще не создан, ссылка на это свойство заставит дескриптор быть созданным ».

Итак, мой регистратор обертывает форму, а его конструктор делает:

   public SimpleProgressDialog() {
       var h = form.Handle; // dereference the handle
   }

Решение кажется слишком простым, чтобы быть правильным. Меня особенно интересует, почему это, казалось бы, слишком простое решение безопасно или небезопасно для использования.

Есть комментарии? Я что-то упустил?

РЕДАКТИРОВАТЬ: Я НЕ прошу альтернативы. Не спрашивая, как использовать NLog или Log4net и т. Д., Если бы я был там, я бы написал страницу обо всех ограничениях клиентов в этом приложении и т. Д.

По количеству голосов за, есть много других людей, которые тоже хотел бы знать ответ.

12
задан codenheim 5 June 2014 в 17:06
поделиться