2010-02-23 2 views

ответ

1

управление Windows с помощью объектной модели (COM) компонентной модели однопоточных квартир (СТО), потому что эти основных элементы управления квартирой резьбы. Кроме того, многие элементы управления используют насос сообщений для многих операций. Эта модель говорит, что все вызовы функций для каждого элемента управления должны быть в том же потоке, который создал элемент управления. Invoke (и BeginInvoke и EndInvoke) метод маршалов вызывает соответствующий поток.

От более эффективного C# Билла Вагнера. Пункт 16.Понять вызовы по перекрестным линиям в Windows Forms и WPF

0

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

Фактический ответ на данный вопрос содержится во втором абзаце данной статьи MSDN =)

Доступ к Windows Forms управления не по своей сути поточно. Если у вас есть два или более потока, управляющих состоянием элемента управления, можно заставить элемент управления перейти в несогласованное состояние. Возможны другие связанные с потоком ошибки, такие как условия гонки и взаимоблокировки. Важно убедиться, что доступ к вашим элементам управления выполняется поточно-безопасным способом.

Вы должны проверить, можно ли получить доступ к управлению сразу, без косвенности (проверки свойства InvokeRequired), если вы не можете, вы должны получить доступ к нему в асинхронном режиме (очень упрощенное объяснения: система будет ждать, пока он может безопасно доступ a control)

+0

И как может делегат async избежать этого? – smwikipedia

1

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

1

Суть заключается в следующем: вы не должны обновлять элементы управления пользовательским интерфейсом из потока, отличного от потока, на котором был создан элемент управления (UI/Main Thread). В противном случае вы можете увидеть какое-то непредсказуемое поведение.

Если вам необходимо обновить пользовательский интерфейс из рабочего потока (кроме основного потока), перед обновлением пользовательского интерфейса вам нужно переключиться обратно в пользовательский интерфейс.

В статье предлагается использовать

  • IsInvokeRequired (который возвращает истину, если текущий поток не один, в котором был создан пользовательский интерфейс.) И Invoke(delegate), запускающий делегат на правильном потоке/UI. Это полезно, если вы хотите обновить UI между процессом async. например обновить прогресс в пользовательском интерфейсе.

  • BackgroundWorker, который выполняет зарегистрированные обработчики на своем асинхронном событии DoWork. в рабочем потоке и запускает зарегистрированные обработчики на его событие RunWorkerCompleted в вызывающем потоке. Это идеально, если вы хотите обновить интерфейс с чем-то после задача async завершена. например опубликовать Выполны указания на UI

Смежные вопросы