UI线程的定义是什么?.NET应用程序中只有一个UI线程吗?

14 .net multithreading

什么是UI线程?.NET应用程序中只有一个UI线程吗?

Ada*_*son 13

(提前简化)

UI线程是单线程公寓线程,用于创建各种用户界面对象(在Winforms中,这意味着控件).按照惯例和规则,只能从用于创建它的线程中访问Control ; 否则可以并且将产生意想不到的结果,从视觉上的怪异一直到崩溃.

除非您明确创建更多,否则Windows窗体应用程序中只有一个UI线程.虽然你可以创建另一个线程并启动消息循环,但是你想要这样做的原因很少,并且两个不同的UI线程不能相互"交谈",而不是任何其他线程可以与UI线程交谈.

  • +1提及你可以做到这一点,但这很少应该做的事情...... (2认同)

Han*_*ant 9

UI线程具有许多使其特殊的特征:

  • Windows有一个与该线程关联的消息队列.一旦在线程上创建了第一个窗口,就会发生这种情况.
  • 该线程运行一个消息循环,允许Windows将消息发送到窗口.一旦调用Application.Run(),就会创建消息循环.
  • COM在线程上初始化,请求单线程单元.STA必须允许许多Windows功能正常工作,这些功能在设计上不是线程安全的.COM确保始终以线程安全的方式调用这些功能,并根据需要将调用从工作线程封送到STA线程.这些功能的示例包括Drag + Drop,剪贴板,shell对话框(OpenFileDialog等),WebBrowser等ActiveX控件,SetWindowsHookEx设置的窗口挂钩,屏幕阅读器,UI自动化提供程序使用的可访问性提供程序等.所有外部代码,都不是线程安全的.
  • 线程永远不会阻塞任何操作,它保持响应,因此它可以根据需要调度Windows消息,以保持用户界面响应和COM编组请求流动.例如,明确禁止调用WaitHandle.WaitAny()并生成异常.CLR具有对WaitOne()的特定支持,并且lock抽取内部消息循环以避免死锁.

几乎总是选择进程的启动线程作为UI线程,尽管这不是一个硬性要求.STA状态由Main()方法的[STAThread]属性选择.

您可以通过确保满足上述要求来创建UI线程.在Winforms应用程序中看起来像这样:

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

这会创建第二个窗口,在自己的UI线程上运行.这种安排的一个典型问题是你现在有两个独立的窗口,它们根本没有相互关联.第2个窗口不能由1st拥有,它有自己的Z-order独立于1st.很难被用户处理.SystemEvents.UserPreferenceChanged事件值得注意,它将不可避免地在错误的线程上触发它的事件并且容易导致死锁.很多WinForms控件都订阅它.除了在极少数情况下,如启动画面,这根本不会改善用户界面.