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.
In production, the app occasionally throws an exception relating to GDI errors or failing to load an 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.
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? 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. I would prefer option 1 with a try catch wrapped around the code you mentioned.
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. 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. 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.