【问题标题】:Setting Form.Owner to a form from a different thread将 Form.Owner 设置为来自不同线程的表单
【发布时间】:2009-11-02 11:57:58
【问题描述】:

我的应用程序(C#、VS2008)通过网络从数据库(SQL Server 2008 Express)加载信息。在(可能)较长的等待期间,我希望在不同的线程上出现一个“正在加载...”对话框,但前提是该操作需要超过特定的时间段(比如 500 毫秒)。

所以,到目前为止,我的加载表单在 500 毫秒后显示(如果操作持续那么长时间),而没有设置加载对话框表单的所有者(即调用 LoadingDialog.ShowDialog()),但是当我尝试调用 LoadingDialog. ShowDialog(IWin32Window owner) 将所有者设置为主窗体(通过线程的参数传入) 我得到有关跨线程访问控件的 InvalidOperationException。

我的基本问题是:我可以创建并 ShowDialog 一个将所有者参数设置为另一个线程上的表单的表单吗?我想这样做,以便加载对话框在应用程序的其余部分是模态的,即像任何其他对话框一样获得焦点并不允许在其他地方输入。

谁能给点建议?我读过很多关于没有运气的闪屏,也有关于没有运气的 Invoke 和 BeginInvoke。我有什么不同的方法可以解决这个问题吗?

如果您不明白,请随时要求澄清。

谢谢(正如他们用法语所说的那样),

雅各布。

【问题讨论】:

  • 不,你不能这样做,甚至不要尝试。
  • 为什么要将对话框放在不同的线程上?

标签: c# multithreading forms owner


【解决方案1】:

您应该在后台线程中运行您的长进程,然后将您的 Loading... 表单显示为非模态对话框。这样,用户可以看到正在加载的指示,但在加载过程中仍会与系统的其他部分进行交互。

另一个选项是在状态栏或类似的地方显示加载进度。关键是要确保长操作在后台线程上完成,并且所有 GUI 逻辑都在 GUI 线程上完成。

一个好的线程格式可能看起来像(这只是用于演示目的的伪代码 - 您需要使用 Invoke 来获得适当的线程):

RunInBackground(DoLongOperation);
ShowLoadingDialog();
...

DoLongOperation()
{
    LongOperation();
    RunOnGUI(FinishLongOperation);
}

FinishLongOperation()
{
   CloseLoadingDialog();
}

【讨论】:

    【解决方案2】:

    所有 UI 组件都在单个线程上运行,该线程通过 win32 消息循环运行。您不能在另一个线程中运行任何 UI 组件。这种架构自 Windows 3.1 以来一直存在。

    【讨论】:

    • 在 Win32 中,您可以在多个线程上运行 UI,只要每个线程运行自己的消息循环即可。 Win32 SDK 中至少有一个示例可以证明这一点。我不知道这在 WinForms 中是否可行,而且我自己从来没有理由在 Win32 或 WinForms 中这样做。
    【解决方案3】:

    您可以根据需要创建任意数量的 UI 线程。以下代码应该可以解决问题:

        Thread thread = new Thread(new ThreadStart(() => Application.Run(new MyForm())));
        thread.SetApartmentState(ApartmentState.STA);
        thread.IsBackground = true;
        thread.Start();
    

    【讨论】:

      猜你喜欢
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多