Есть сотни примеров в блогах и т. Д. О том, как реализовать фонового работника, который регистрирует или присваивает статус элементу переднего плана 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 () завершается неудачей.
Я знаком с различными подходами, включая использованиеСобытие 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 и т. Д., Если бы я был, я бы написал страницу обо всех клиентских ограничениях в этом приложении и т. Д.
По количеству голосов было многодругие люди, которые хотели бы знать ответ тоже.