Выполнение поточно-безопасных вызовов для оконных элементов управления - PullRequest
2 голосов
/ 23 февраля 2010

Статья MSDN: Как сделать потокобезопасные вызовы элементов управления Windows Forms говорит, что мы должны использовать async делегат, чтобы сделать вызов. Но почему асинхронный делегат делает вызов безопасным?

Ответы [ 4 ]

1 голос
/ 23 февраля 2010

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

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

1 голос
/ 23 февраля 2010

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

1 голос
/ 23 февраля 2010

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

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

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

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

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

0 голосов
/ 23 февраля 2010

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...