【问题标题】:Creating a Form and using Form.ShowDialog on a background thread在后台线程上创建表单并使用 Form.ShowDialog
【发布时间】:2012-06-06 08:03:08
【问题描述】:

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

  1. 创建表单,
  2. 在该表单上调用 ShowDialog

似乎我会遵守以下规则: Winforms 控件必须在创建它们的线程上进行修改。

从我所做的一些阅读看来,ShowDialog 似乎会创建自己的消息泵,这样我就不必担心在已经有消息泵的线程上创建表单。

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

【问题讨论】:

  • +1 这是个好问题。

标签: c# winforms multithreading


【解决方案1】:

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

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

【讨论】:

  • 谢谢汉斯。使用 Application.OpenForms[0] 有什么缺点吗?它总是保证存在吗?
  • @MattSmith:应该是,是的,但我确实发现 this SO post 详细说明了一个错误,不确定是否仍然存在。
  • 它仍然存在,但是很容易避免。
【解决方案2】:

是的,您可以这样做,但是如果您希望对话框实际上像模态对话框一样运行(即,阻止父窗口,我假设您想要这样做,因为您正在调用 ShowDialog)然后准备好失望.

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

【讨论】:

  • 好点。就我而言,我收到了一个回调,当时可能会或可能不会显示其他 ui。我没有理由不在主 ui 线程上,我只是没有可以用来调用的控件。
猜你喜欢
  • 1970-01-01
  • 2012-01-08
  • 2014-04-02
  • 2012-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-28
相关资源
最近更新 更多