Поток пользовательского интерфейса имеет ряд характеристик, которые делают его особенным:
- 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 подписаться на него. За исключением редких случаев, таких как заставка, это совсем не улучшает интерфейс пользователя.