C#: 在单独的线程上预加载窗体

4

我有一些表格,它们需要从数据库中获取一些数据在其Load事件处理程序中,所以打开它们需要一点时间。

是否可能在单独的线程中加载表单并在完成后向用户显示?

如果无法在引发Load事件处理程序的情况下加载它们,那么也许使用IPreloadable接口可以通过Preload方法来解决问题,然后将慢速加载的内容移入其中。如果可以从单独的线程中显示表单的话...猜测我需要使用Invoke或类似的东西?


也许我漏掉了什么,但您可以先隐藏窗体,然后启动 BackgroundWorker 的 StartAsynchronous() 方法,在 BackgroundWorker 完成时显示窗体。看起来太简单了。 :) - KiNgMaR
1个回答

2
如果您在不同的线程上加载不同的表单,则在表单之间进行调用时必须非常小心-您需要在许多地方使用Control.Invoke/BeginInvoke。请注意,虽然每个顶级窗口可以在不同的线程上运行,但窗口中的所有控件都必须在该窗口的线程上创建(或者说,它们必须具有其句柄)。为什么不在后台加载数据库信息,然后在完成后构建实际的表单并显示它?(在此之前,您可能想要更改为等待光标,或者可能在某个地方放置“正在加载数据…”状态消息。)

当然需要设置状态消息和可能是跑马灯的状态栏,而这个过程发生时。但是如何在后台加载数据库信息,然后构建实际的窗体呢?比如,在构造函数中进行而不是在加载事件处理程序中进行吗?或者根本不是在窗体中进行,而是在父窗体或其他地方进行? - Svish
使用BackgroundWorker来完成,然后让RunWorkerCompleted事件处理程序使用刚刚获取的数据。 - Jon Skeet
那么,是先显示空控件的窗体,然后使用BackgroundWorker获取数据并创建缺失/填充控件呢?还是先使用BackgroundWorker获取数据,然后显示窗体并填充控件? - Svish
是的。个人而言,我可能会选择后者。 - Jon Skeet
太棒了。那我得试试其中之一了 =) - Svish
我可以问一下是否还有其他方法吗?我们使用供应商提供的控件。如果有很多控件,InitializeComponent() 将需要花费时间。(我们稍后进行数据库附加,因此只是空白显示/初始化组件需要时间)。所以我们想做类似于 Form mainForm; ,然后一个线程 mainform = new MainForm(someparamter); 显示另一个登录表单,然后在登录表单中从普通程序加入 mainForm 并在之后加入 Application.run(mainForm)。 - Offler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接