Причина ограничения потока элемента .NET UI - PullRequest
8 голосов
/ 02 июня 2010

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

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

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

Ответы [ 3 ]

2 голосов
/ 02 июня 2010

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

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

1 голос
/ 02 июня 2010

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

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

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

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

0 голосов
/ 02 июня 2010

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

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

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