Причина.NET ограничение потока элемента UI

Мы знаем, что не возможно выполнить код, который управляет свойствами любого элемента UI от любого потока кроме потока, на котором инстанцировали элемент... Мой вопрос: Почему?

Я помню, что, когда мы использовали элементы пользовательского интерфейса COM, (за Основные 6.0 дней COM/Visual), что все элементы UI были созданы с помощью COM-классов и co-классов, которые сохранили их ресурсы с помощью модели памяти, называемой Локальной памятью потока (TLS), но поскольку я вспоминаю, это требовалось из-за чего-то связанного со способом, которым COM-компоненты были созданы и не должны относиться к.NET элементы UI. Какова базовая причина, почему это ограничение все еще существует?

Это, потому что базовая Операционная система все еще использует основанный на COM Win32 классы API для всех элементов UI, даже те, которыми управляют в управляемом приложении.NET?

8
задан Peter Mortensen 13 December 2017 в 00:16
поделиться

3 ответа

AFAIK, он более простой, чем даже COM. Это относится к старому доброму Windows API. Я считаю, что окна в Windows должны принадлежать потоку, точка. У каждого потока есть собственный насос сообщений, отправляющий сообщения в принадлежащие ему окна. Это довольно фундаментальная конструкция Windows - может быть, в наши дни немного архаичная, но фундаментальная.

Мне кажется, что это сходство потоков помогает для взаимодействия, когда вам нужно интегрировать WPF в приложения Windows Forms или если вам нужно обезопасить объект Windows где-то еще в вашем приложении, используя HWND, который вы где-то получили .. Вероятно, это также то, что позволяет более старым версиям Windows (XP) размещать приложения WPF без каких-либо серьезных архитектурных изменений самой ОС.

2
ответ дан 6 December 2019 в 00:54
поделиться

Похоже, вы имеете в виду WPF, а не общее программирование Windows API. Я не специалист по внутреннему устройству WPF, но вот несколько моментов о том, почему хранение манипуляций с пользовательским интерфейсом в одном потоке пользовательского интерфейса является хорошей идеей:

  1. Избегайте взаимоблокировок. Когда у вас работает несколько потоков, все общие ресурсы должны быть защищены какой-то блокировкой. Когда имеется несколько блокировок, существует высокий риск застревания в тупиковой ситуации - поток A владеет блокировкой 1, но ожидает блокировки 2, поток B владеет блокировкой 2, но ожидает блокировки 1. Этого можно избежать с помощью строгого порядка следования. приобретение блокировки, но человеческая природа не оправдывает ожиданий.
  2. Уменьшите потребность в дорогостоящих замках. Если вы можете потребовать, чтобы все операции пользовательского интерфейса выполнялись в потоке пользовательского интерфейса, вы можете устранить множество блокировок, необходимых для защиты внутренних данных.
  3. Уменьшите риск создания дескрипторов окон, принадлежащих потокам, не имеющим зацикливания сообщений.

Последний пункт связан с Win API.Когда создается дескриптор окна, он привязывается к потоку, который вызвал CreateWindow. Сообщения, отправленные на этот дескриптор окна, будут помещены в очередь сообщений, связанную с этим потоком. Если этот поток не обрабатывает оконные сообщения, окно не будет отвечать - пользовательский интерфейс заморожен. Если другой поток пытается отправить сообщение в это окно, этот поток также будет заморожен в ожидании завершения синхронного вызова. Этот снежный ком довольно быстро превращается в безобразие. Вот почему важно убедиться, что вы создаете дескрипторы окон только в потоках, которые подготовлены для обработки оконных сообщений.

Почему очередь сообщений дескриптора окна привязана к определенному потоку? Не знаю, но уверен, что ответ нетривиальный.

1
ответ дан 6 December 2019 в 00:54
поделиться

Из http://msdn.microsoft.com/en-us/library/ms741870.aspx :

Исторически Windows разрешает пользовательский интерфейс элементы, к которым будет иметь доступ только поток, который их создал. Это означает что фоновый поток, отвечающий за какая-то длительная задача не может обновить текстовое поле, когда оно будет завершено. Окна делает это для обеспечения целостности Компоненты пользовательского интерфейса. Список может выглядеть странно, если его содержимое обновлялось фоновым потоком во время рисование.

0
ответ дан 6 December 2019 в 00:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: