我的表单上有两个控件:一个带有工作列表和面板的列表框,它充当显示关于工作细节(卡片)的容器。 当用户点击工人的名字时,我在面板上显示卡片。一张卡片是一个用户控件,带有一些相当简单的用户界面(2个组框,3个文本框和几个标签)和简单的逻辑(设置标签的前景色)。缓慢处理UserControl
卡片在运行时创建。以前的卡片会从面板中移除,新的卡片将被添加 - 每名工人的卡片数量为1到4个。这里变得很有趣。 一切工作正常,直到约。第五次点击工人。似乎GC启动了,旧卡(之前删除)需要约两秒钟(0.3s x先前删除的卡的数量)才能处理并显示新的卡。如果工人之间的移动工作很好,那么在这一点上会变得非常缓慢。 经过一番探索后,我找到了我使用过的控件的方法Dispose
。致电base.Dispose()
大约需要0.3秒。
这里是我的代码:
private void ShowCards(List<Work> workItems) {
var y = 5;
panelControl1.SuspendLayout();
panelControl1.Controls.Clear();
foreach (var work in workItems) {
var card = new Components.WorkDisplayControl(work);
card.Top = y;
card.Left = 10;
y += card.Height + 5;
panelControl1.Controls.Add(card);
}
panelControl1.ResumeLayout(true);
Application.DoEvents();
}
我试过到目前为止:
- 藏身卡,而不是处置 - 移动员工之间 当它工作得更快,但点球支付时关闭表格
- 隐藏卡片,并有一个单独的线程,配置它们 - 没有变化
- 测试添加10张卡片d立即处理它们 - 慢
- 测试添加10张卡并立即处理它们在构造函数中 - FAST!
- 取代的DevExpress与“正常”的控制 - 没有改变
- 手动处置旧卡而不是改变工人的时候移除它们的 - 工人之间的一举一动变慢:
for (var ix = panelControl1.Controls.Count - 1; ix >= 0; --ix) { panelControl1.Controls[ix].Dispose();}
- 剖析它 - 这就是我是如何发现问题在
Dispose
。我可以跟踪它归结为Control.DestroyHandle
- 调用
Controls.Clear()
在我的控制Dispose
方法 - 超奇怪的行为和异常 - 取消了所有从我的用户控件 - 快一点点,但仍然缓慢
- 隐藏
panelControl1
时删除和添加卡 - 没有变化 - 打开背景GC关闭 - 没有变化
- 将卡
AddRange
由于从构造函数调用时相同的功能运行速度很快,我相信原因必须在(控制)句柄中的某处。
我只是找不到这种奇怪行为的原因。我会很感激任何想法....
更新:当研究GC和控制之间的连接。处置我发现this excellent answer
处置与垃圾收集器没有任何关系。您以非常危险的方式使用Controls.Clear(),它不会处理控件。运行Taskmgr.exe,进程选项卡。查看+选择列并勾选USER对象和GDI对象。确保这些值对于您的应用程序是稳定的,并且不会毫无束缚地攀登。联系devexpress获取更多支持。 –
@HansPassant感谢您的意见和建议。 USER和GDI对象的数量不会改变。 “危险的方式”是什么意思?我只是希望他们从我的容器中移除。 –