2010-05-04 7 views

ответ

13

(Облегчение вперед)

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

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

+2

+1 за то, что вы можете это сделать, но это редко так, как все должно быть сделано ... –

+0

Так что, когда вы делаете новую тему(). Start() внутри STAThread? – 2010-05-04 19:30:01

+0

@Griever: начинается новый поток, но он полностью отделен от потока пользовательского интерфейса. Выполнение нового запуска нити создает новый, несвязанный поток. –

0

EDITED правильность:

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

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

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

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

+1

Это неправда. Различные формы в Windows Forms используют ** тот же ** поток. Насос сообщения делает их отзывчивыми. –

+0

У меня было это обратное, модальные диалоги требуют нового потока, немодальные диалоги не требуют * нового потока. Точка по-прежнему утверждает, что обычные потоки могут стать нитями ui, когда из них открывается новая форма. – David

+0

Это все еще не соответствует действительности. «Запуск формы» из нового потока без особой заботы о начале цикла сообщений вызовет всевозможные проблемы, в том числе (в большинстве случаев), из-за отсутствия STA по умолчанию. –

7

ПИ нить имеет ряд характеристик, которые делают его особенным:

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

+0

Мне нравится ваш подробный ответ. – 2010-05-05 06:33:27

Смежные вопросы

 Смежные вопросы