[英]What is the safest way to clear a container's Controls property and make sure the controls are properly disposed?
在WinForms应用程序中,我有多个实例,在其中我将一个控件添加到容器中以响应用户操作( panel.Controls.Add(new CustomControl(...))
),然后稍后清除面板( panel.Controls.Clear()
)并重新使用它。
在生产中,该应用偶尔会引发与GDI错误或无法加载ImageList
有关的异常。 这通常发生在资源有限的计算机上,以及一天中大量使用该应用程序的用户。 很明显,我有一个GDI句柄泄漏,应该处理从容器中清除的控件,但是我发现的任何解释都不清楚应在何时何处放置控件。
我应该在清理容器后立即处置儿童控件吗? 就像是:
var controls = new List<Control>(_panel.Controls.Cast<Control>());
_panel.Controls.Clear();
foreach (var c in controls) c.Dispose();
还是应该在列表中跟踪控件并在容器的Dispose()
方法中调用dispose? 如:
List<Control> _controlsToDispose = new List<Control>();
void ClearControls()
{
_controlsToDispose.AddRange(_panel.Controls.Cast<Control>());
_panel.Controls.Clear();
}
void Dispose()
{
...
foreach (var c in _controlsToDispose) c.Dispose();
}
选项2引入了另一个您需要清除的列表,这些列表将占用更多的内存。 我希望选项1带有围绕您提到的代码的try catch。
在(以某种有效的方式)纠正了我的应用没有处理清除的控件的所有情况后,我可以提出几点:
ListViewItem
或TreeViewItem
的集合的Tag
属性中。 它们不应该被清除,但是整个列表应该被迭代,并在父级的Dispose()
方法中调用((Control)item.Tag).Dispose()
。 在管理控制生命周期和处置方面,我找不到任何最佳实践或建议。 我猜规则是,如果一个控件没有结束,那么它的生命就嵌套在一个被处置的控件上,无论何时不再使用它,都必须手动处置它,或者在父控件的Dispose()
最晚的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.