[英]What is the safest way to clear a container's Controls property and make sure the controls are properly disposed?
In a WinForms application I have a number of instances where I add a control to a container in response to a user action ( panel.Controls.Add(new CustomControl(...))
), then later clear the panel ( panel.Controls.Clear()
) and reuse it. 在WinForms应用程序中,我有多个实例,在其中我将一个控件添加到容器中以响应用户操作(
panel.Controls.Add(new CustomControl(...))
),然后稍后清除面板( panel.Controls.Clear()
)并重新使用它。
In production, the app occasionally throws an exception relating to GDI errors or failing to load an ImageList
. 在生产中,该应用偶尔会引发与GDI错误或无法加载
ImageList
有关的异常。 This usually happens on machines with limited resources and with users that use the application intensively over the day. 这通常发生在资源有限的计算机上,以及一天中大量使用该应用程序的用户。 It seems pretty obvious that I have a GDI handle leak and that I should be disposing the controls that get cleared from the container, however any explanations I can find are vague about where and when the control should be disposed.
很明显,我有一个GDI句柄泄漏,应该处理从容器中清除的控件,但是我发现的任何解释都不清楚应在何时何处放置控件。
Should I dispose the child controls immediately after clearing the container? 我应该在清理容器后立即处置儿童控件吗? Something like:
就像是:
var controls = new List<Control>(_panel.Controls.Cast<Control>());
_panel.Controls.Clear();
foreach (var c in controls) c.Dispose();
Or should I track the controls in a list and call dispose in the container's Dispose()
method? 还是应该在列表中跟踪控件并在容器的
Dispose()
方法中调用dispose? Such as: 如:
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();
}
Option 2 introduces another list which you would need to cleanup and it will take some more memory for those items. 选项2引入了另一个您需要清除的列表,这些列表将占用更多的内存。 I would prefer option 1 with a try catch wrapped around the code you mentioned.
我希望选项1带有围绕您提到的代码的try catch。
After (somewhat effectively) correcting any cases where my app wasn't disposing cleared controls I can come up with some points: 在(以某种有效的方式)纠正了我的应用没有处理清除的控件的所有情况后,我可以提出几点:
Tag
property of a collection of ListViewItem
s or TreeViewItem
s. ListViewItem
或TreeViewItem
的集合的Tag
属性中。 They shouldn't be disposed on clear, but the entire list should be iterated and ((Control)item.Tag).Dispose()
called in the parent's Dispose()
method. Dispose()
方法中调用((Control)item.Tag).Dispose()
。 I haven't been able to find any best practices or recommendations on managing control lifecycle and disposal. 在管理控制生命周期和处置方面,我找不到任何最佳实践或建议。 I guess the rule is just that if a control doesn't end it's life nested on a control that is disposed, it has to be disposed manually, whenever it isn't going to be used again, or in the parent control's
Dispose()
method at the latest. 我猜规则是,如果一个控件没有结束,那么它的生命就嵌套在一个被处置的控件上,无论何时不再使用它,都必须手动处置它,或者在父控件的
Dispose()
最晚的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.