C# 在后台线程上创建窗体并使用Form.ShowDialog

C# 在后台线程上创建窗体并使用Form.ShowDialog,c#,winforms,multithreading,C#,Winforms,Multithreading,使用Winforms, 如果我在一个不是“主”ui线程的线程上,我可以安全地 创建一个表单 调用该窗体上的ShowDialog 我似乎要遵守以下规则: 必须在创建Winforms控件的线程上修改Winforms控件 从我读到的一些资料来看,ShowDialog似乎将创建自己的消息泵,这样我就不必担心在已经有消息泵的线程上创建表单 问题的背景是,我得到了一个回调,我想在其中显示一些Winforms UI,但我没有访问任何其他可用于调用主线程的UI的权限。是的,您可以这样做,但如果您希望该对话框实际

使用Winforms, 如果我在一个不是“主”ui线程的线程上,我可以安全地

  • 创建一个表单
  • 调用该窗体上的ShowDialog
  • 我似乎要遵守以下规则: 必须在创建Winforms控件的线程上修改Winforms控件

    从我读到的一些资料来看,ShowDialog似乎将创建自己的消息泵,这样我就不必担心在已经有消息泵的线程上创建表单


    问题的背景是,我得到了一个回调,我想在其中显示一些Winforms UI,但我没有访问任何其他可用于调用主线程的UI的权限。

    是的,您可以这样做,但如果您希望该对话框实际上像一个模态对话框一样工作(也就是说,阻止父窗口,我认为这是您想要的,因为您正在调用
    ShowDialog
    ),然后做好失望的准备


    您实际上要解决的问题是什么。听起来您需要一个不阻塞的模式对话框,这有点奇怪。如果您解释手头的问题,可能存在一个您尚未考虑的解决方案。

    这大致正确,尽管调用线程的SetApartmentState()非常重要方法将线程切换到STA。这对于许多UI操作非常重要,包括剪贴板、拖放和shell对话框。而且,当在线程上创建的窗体不在前台并隐藏在另一个窗口后时,您通常会遇到糟糕的Z顺序问题。或者有在前台实际移动的坏习惯当用户不期望时,意外地抓取鼠标单击或击键


    这些都是很难解决的问题,它们确实会让你的应用程序变得不稳定。没有理由不调用引用,你也可以通过某种方式将其传递给类。如果真的有必要,你总是可以依靠Application.OpenForms[0]。

    谢谢Hans。使用Application.OpenForms[0]有任何缺点吗?它总是保证存在吗?@MattSmith:应该存在,是的,但我确实发现了一个bug,不确定它是否仍然存在。它仍然存在,但很容易避免。这一点很好。在我的情况下,我收到了一个回调,当时可能会有或者可能没有其他ui显示。我没有理由不在主ui线程上,我只是没有控制我可以用+1来调用这是个很好的问题。