什么是UI线程?.NET应用程序中是否只有一个UI线程?
UI线程是单线程公寓线程,用于创建各种用户界面对象(在Winforms中,这意味着控件)。按照约定和规则,一个控件只能从创建它的线程中访问;否则可能会产生意想不到的结果,从视觉上的奇怪到崩溃。
除非你明确地创建更多,否则在Windows Forms应用程序中只有一个UI线程。虽然你可以创建另一个线程并启动消息循环,但很少有理由这样做,并且两个不同的UI线程无法“交流”,就像任何其他线程不能与UI线程交流一样。
UI线程有一些特殊的特点:
lock
的特定支持,通过泵送内部消息循环来避免死锁。进程的启动线程几乎总是被选为UI线程,尽管这不是硬性要求。 STA状态由Main()方法中的[STAThread]属性选择。
你可以通过确保满足上述要求来创建一个UI线程。在Winforms应用程序中,这可能看起来像这样:
var ui = new Thread(() => { Application.Run(new Form2()); });
ui.SetApartmentState(ApartmentState.STA);
ui.Start();
这会创建第二个窗口,运行在自己的UI线程上。这种安排通常会遇到一个问题,您现在有两个单独的窗口,它们根本没有关联。第二个窗口不能被第一个窗口所拥有,它具有独立于第一个窗口的Z顺序。对于用户来说,这很难处理。SystemEvents.UserPreferenceChanged事件很显著,它必然会在错误的线程上触发其事件,这有可能导致死锁。许多WinForms控件都订阅了它。除了像启动画面这样的罕见情况外,这根本不会改善用户界面。
已编辑以确保正确性:
在 Windows Forms 中,每个活动应用程序都有一个 UI 线程,WPF 也有类似的概念。
例如:当您启动应用程序时,会有一个线程,当调用 Application.Run(new Form1()); 时,它就成为了 UI 线程。
如果您尝试在运行时执行 Application.Run(new Form2());,则会收到“System.InvalidOperationException: 在单个线程上启动第二个消息循环不是有效操作。请改用 Form.ShowDialog。”的错误提示。
如果您确实需要两个单独的窗体不共享同一线程,则需要创建一个新线程,然后调用 Application.Run(new MyForm()) 等等。但这并不常见。