1

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

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

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

任何人都可以提供建议吗?我读过很多关于没有运气的闪屏,也有关于没有运气的 Invoke 和 BeginInvoke。我应该以不同的方式解决这个问题吗?

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

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

雅各布。

4

3 回答 3

1

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

于 2009-11-02T12:01:54.430 回答
1

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

    Thread thread = new Thread(new ThreadStart(() => Application.Run(new MyForm())));
    thread.SetApartmentState(ApartmentState.STA);
    thread.IsBackground = true;
    thread.Start();
于 2010-11-05T03:08:01.967 回答
1

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

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

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

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

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

FinishLongOperation()
{
   CloseLoadingDialog();
}
于 2011-04-26T15:01:45.007 回答