我的表单上有两个控件:一个带有工作人员列表的列表框和一个面板,该面板用作显示有关其工作的详细信息(卡片)的容器。当用户点击工人的名字时,我会在面板上显示卡片。卡片是一个用户控件,具有一些相当简单的 UI(2 个组框、3 个文本框和几个标签)和简单的逻辑(设置标签的前景色)。
卡片是在运行时创建的。以前的卡片从面板中删除,新的卡片被添加 - 每个工人的卡片数量是 1 到 4。这里很有趣。一切正常,直到大约。第五次点击工人。似乎 GC 开始了,大约需要两秒钟(0.3sx 数量的先前移除的卡)来处理旧卡(之前移除)并显示新卡。如果以前在工人之间移动效果很好,那么它会变得非常缓慢。经过一番探索,我发现问题在于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 张卡片并立即处理它们进行测试 - 慢
- 添加 10 张卡片并立即在构造函数中处理它们进行测试- 快!
- 用“正常”替换了 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 和 Control.Dispose 之间的联系时,我发现了这个很好的答案