我有一个带有多个组合框/列表框等的Windows窗体(C#)项目,这些项目在表单加载时会填充。
问题是组合框/列表框的加载速度很慢,并且由于在表单尝试显示时完成加载,因此在填充所有控件之前不会显示整个表单。在某些情况下,这可能超过20秒。
如果有一个Form_finished_loaded类型的事件,我可以把我的代码放在那里,但是我无法找到在完成表单绘制基本控件后触发的事件。
我有一个要求 - 加载必须在主线程中完成(因为我从非线程友好的COM应用程序中获取项目)。
我找到了一个可能的解决方案,但也许有更好的方法? 我可以在创建表单时创建一个System.Timer.Timer,并在大约1秒后调用第一个Tick,然后从该tick中填充列表。这使表单在开始填充列表之前有足够的时间显示。
有没有人有关于如何延迟加载控件的其他提示?
答案 0 :(得分:6)
首次显示表单时会出现Shown event。“此外,您可能希望使用BeginUpdate and EndUpdate函数来更快地填充组合框。
答案 1 :(得分:1)
它具有某种解决方法的气味,但这种方法应该满足您的需求:
private bool _hasInitialized = false;
private void Form1_Shown(object sender, EventArgs e)
{
if (!_hasInitialized)
{
ThreadPool.QueueUserWorkItem(state =>
{
Thread.Sleep(200); // brief sleep to allow the main thread
// to paint the form nicely
this.Invoke((Action)delegate { LoadData(); });
});
}
}
private void LoadData()
{
// do the data loading
_hasInitialized = true;
}
它的作用是它在显示表单时做出反应,检查它之前是否已经初始化,如果没有,它会在主线程上调用LoadData方法之前产生一个等待片刻的线程。这将允许表格正确绘制。通过简单地调用this.Refresh()
也许可以实现同样的目标,但我喜欢让系统决定如何开展工作的想法。
我仍然会尝试将数据加载到工作线程上,调用主线程来填充UI(如果它完全可以使用COM组件)。
答案 2 :(得分:0)
您可以从调用COM组件的Web服务获取数据吗?
这样,您可以在开始时在Locked表单上显示空控件,进行异步调用以获取数据,并在返回时填充相应的组合,并且一旦加载了所有组合,您就可以解锁表单用户使用。
答案 3 :(得分:0)
您可以监听VisibleChanged
事件,并且第一次将值设置为true时,您可以放置初始化代码。
答案 4 :(得分:0)
FormShown不是您正在寻找的活动吗?
答案 5 :(得分:0)
当你说由于COM你不能使用后台线程时你是什么意思?我在我的应用程序中使用了许多COM组件,并在后台线程上运行它们。
如果您创建一个新线程作为STAThread,您可以在非UI线程上加载ComboBox / ListBox。 IIRC ThreadPool将工作线程分配为MTAThread,因此您需要手动创建线程而不是使用ThreadPool.QueueUserWorkItem。