Каково определение потока пользовательского интерфейса? В приложении .NET есть только один поток пользовательского интерфейса? - PullRequest
13 голосов
/ 04 мая 2010

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

Ответы [ 3 ]

13 голосов
/ 04 мая 2010

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

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

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

8 голосов
/ 05 мая 2010

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

  • 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();

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

0 голосов
/ 04 мая 2010

отредактировано для правильности:

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

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

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

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

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