Подтвердить что ты не робот

Каково определение потока пользовательского интерфейса? Есть ли только один поток пользовательского интерфейса в приложении .NET?

Что такое поток пользовательского интерфейса? Есть ли только один поток пользовательского интерфейса в приложении .NET?

4b9b3361

Ответ 1

(Упрощение вперед)

Нить пользовательского интерфейса представляет собой поток с однопоточной резьбой, который используется для создания различных объектов пользовательского интерфейса (в Winforms это означает Controls). По соглашению и правилу Control может быть доступен только из потока, который использовался для его создания; в противном случае может и будет давать неожиданные результаты, от визуальных странностей вплоть до крушения.

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

Ответ 2

Нить пользовательского интерфейса имеет ряд характеристик, которые делают его особенным:

  • В Windows есть очередь сообщений, связанная с потоком. Это происходит, как только первое окно создается в потоке.
  • В потоке выполняется цикл сообщений, позволяющий Windows отправлять сообщения в окна. Цикл сообщения создается, как только вы вызываете Application.Run().
  • COM был инициализирован в потоке, запрашивая однопоточную квартиру. STA необходима, чтобы позволить многим функциям Windows функционировать должным образом, функции, которые не являются потокобезопасными по дизайну. COM гарантирует, что эти функции всегда вызываются поточно-безопасным образом, при необходимости маршируя вызов из рабочего потока в поток STA. Примерами этих функций являются Drag + Drop, буфер обмена, диалоговые окна оболочки (OpenFileDialog и т.д.), Элементы ActiveX, такие как WebBrowser, крючки окон, установленные SetWindowsHookEx, поставщики доступности, такие как используемые устройством чтения с экрана, поставщиками автоматизации пользовательского интерфейса. Весь внешний код, ни один из которых не является потокобезопасным.
  • Нить никогда не блокирует какую-либо операцию, она остается отзывчивой, поэтому она может отправлять сообщения Windows по мере необходимости, чтобы пользовательский интерфейс реагировал и запросы маршалинга COM текла. Например, вызовы WaitHandle.WaitAny() явно запрещены и генерируют исключение. CLR имеет определенную поддержку WaitOne() и lock, перекачивая внутренний цикл сообщений, чтобы избежать тупиковой ситуации.

Начальный поток процесса почти всегда выбирается как поток пользовательского интерфейса, хотя это не является жестким требованием. Состояние STA выбирается атрибутом [STAThread] в методе Main().

Вы можете создать поток пользовательского интерфейса, обеспечив выполнение вышеуказанных требований. Это может выглядеть так в приложении Winforms:

    var ui = new Thread(() => { Application.Run(new Form2()); });
    ui.SetApartmentState(ApartmentState.STA);
    ui.Start();

Это создает второе окно, работающее на свой собственный поток пользовательского интерфейса. Одна типичная проблема, с которой вы столкнулись, состоит в том, что у вас теперь есть два отдельных окна, они не связаны друг с другом вообще. Второе окно не может принадлежать 1-му, у него есть собственный Z-порядок, не зависящий от 1-го. Трудно справиться с пользователем. Событие SystemEvents.UserPreferenceChanged примечательно, оно неизбежно запускает его событие в неправильном потоке и может вызвать тупик. Многие элементы управления WinForms подписывают его. За исключением редких случаев, таких как заставка, это вообще не улучшает пользовательский интерфейс.

Ответ 3

СОЕДИНЕН за правильность:

Существует один поток пользовательского интерфейса для активной APPLICATION в Windows Forms и аналогичная концепция для WPF.

т.е.: Когда вы запускаете приложение, есть один поток, он становится потоком пользовательского интерфейса, когда Application.Run(новый Form1()); называется.

Если вы попытаетесь выполнить Application.Run(новый Form2()); во время выполнения вы получите "System.InvalidOperationException: запуск второго цикла сообщений в одном потоке не является допустимой операцией. Вместо этого используйте Form.ShowDialog."

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