将Form.Owner设置为来自不同线程的表单

时间:2009-11-02 11:57:58

标签: c# multithreading forms owner

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

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

我的基本问题是:我可以创建和ShowDialog表单,其中owner参数设置为另一个线程上的表单吗?我想这样做,以便加载对话框是模式的应用程序的其余部分,即像任何其他对话框一样关注并禁止在别处输入。

有人可以提出建议吗?我已经阅读了关于没有运气的启动画面的堆,也关于Invoke和BeginInvoke没有运气。我应该采取不同的方式吗?

如果您不理解,请随时要求澄清。

Merci(正如他们用法语所说),

雅各。

3 个答案:

答案 0 :(得分:1)

所有UI组件都在单个唯一线程上运行,该线程在win32消息循环上运行。您无法在另一个线程中运行任何UI组件。自Windows 3.1以来,这种架构仍然存在。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

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

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

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

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

FinishLongOperation()
{
   CloseLoadingDialog();
}