Почему только поток пользовательского интерфейса может изменять пользовательский интерфейс? - PullRequest
22 голосов
/ 25 сентября 2010

Я знаю, что, если я изменяю элемент управления из другого потока, я должен позаботиться, потому что WinForms и WPF не позволяют изменять состояние элемента управления из других потоков.1003 *

Если я смогу написать потокобезопасный код, я смог бы безопасно изменить состояние управления.Тогда почему присутствует это ограничение?

Ответы [ 6 ]

23 голосов
/ 25 сентября 2010

В некоторых инфраструктурах GUI есть это ограничение.Согласно книге Параллелизм Java на практике причина этого заключается в том, чтобы избежать сложной блокировки.Проблема заключается в том, что элементы управления графическим интерфейсом могут реагировать на оба события из пользовательского интерфейса, привязку данных и т. Д., Что приводит к блокировке из нескольких различных источников и, следовательно, к риску взаимоблокировок.Чтобы избежать этого, .NET WinForms (и другие пользовательские интерфейсы) ограничивают доступ к компонентам одним потоком и таким образом избегают блокировок.

9 голосов
/ 25 сентября 2010

В случае окон, когда создается элемент управления, обновления пользовательского интерфейса выполняются с помощью сообщений от рассылки сообщений.Программист не имеет прямого управления потоком, на котором работает насос, поэтому появление сообщения для элемента управления может привести к изменению состояния элемента управления.Если бы другому потоку (которым непосредственно управлял программист) было разрешено изменять состояние элемента управления, то для предотвращения повреждения состояния элемента управления должна была бы быть создана какая-то логика синхронизации.Элементы управления в .Net не являются потокобезопасными;это, я подозреваю, по замыслу.Внедрение логики синхронизации во все элементы управления будет дорогостоящим с точки зрения проектирования, разработки, тестирования и поддержки кода, обеспечивающего эту функцию.Программист, конечно, мог бы обеспечить безопасность потока для элемента управления для своего собственного кода , но не для кода в .Net, который работает одновременно с его кодом.Одним из решений этой проблемы является ограничение этих типов действий одним потоком и одним потоком, что упрощает поддержку управляющего кода в .Net.

3 голосов
/ 25 сентября 2010

.NET оставляет за собой право доступа к вашему элементу управления в той ветке, где вы его создали, в любое время.Следовательно, доступы из другого потока никогда не могут быть безопасными для потока.

2 голосов
/ 26 сентября 2010

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

Еще один интересный аспект привязки потока к элементам управления заключается в том, что он может (хотя я подозреваю, что они никогда не будут) использовать шаблон Thread Local Storage .Очевидно, что если вы получили доступ к элементу управления в потоке, отличном от того, в котором он был создан, он не сможет получить доступ к правильным данным TLS, независимо от того, насколько тщательно вы структурировали код для защиты от всех обычных проблем многопоточного кода.

1 голос
/ 12 апреля 2011

Windows поддерживает множество операций, которые, особенно используемые в комбинации, по своей природе не являются поточно-ориентированными.Что должно произойти, например, если один поток пытается вставить какой-либо текст в текстовое поле, начиная с 50-го символа, а другой поток пытается удалить первые 40 символов из этого поля?Windows могла бы использовать блокировки, чтобы гарантировать, что вторая операция не может быть начата до тех пор, пока не завершится первая, но использование блокировок добавит накладные расходы для каждой операции, а также повысит вероятность взаимоблокировки, если действия над одним объектом требуютманипулирование другим.Требование о том, что действия с конкретным окном должны выполняться в конкретном потоке, является более строгим требованием, чем необходимо для предотвращения одновременного выполнения небезопасных комбинаций операций, но его относительно легко анализировать.Использование элементов управления из нескольких потоков и предотвращение конфликтов с помощью каких-либо других средств, как правило, будет более сложным.

1 голос
/ 15 января 2011

На самом деле, насколько я знаю, это был план с самого начала! Любой элемент управления может быть доступен из любого потока! И только потому, что блокировка потока была необходима, когда другому потоку требовался доступ к элементу управления - а также потому, что блокировка дорогая - была создана новая модель потоков, называемая «аренда потока». В этой модели связанные элементы управления будут объединены в «контексты» с использованием только одного потока, что позволит сократить объем необходимой блокировки. Довольно круто, да?

К сожалению, эта попытка была слишком смелой, чтобы преуспеть (и немного более сложной, потому что блокировка все еще требовалась), поэтому старая модель потоков Windows Forms - с одним потоком пользовательского интерфейса и с потоком создания, чтобы претендовать на владение control-- снова используется в wPF для облегчения нашей жизни ...?

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