正确处理/关闭用户控件

时间:2011-11-02 13:39:08

标签: .net winforms memory-leaks garbage-collection

我有一个Windows窗体屏幕,其中一个菜单栏停靠在窗体的左侧,类似于Outlook 2003,并且一个面板占据了窗体右侧的其余部分。

我的左侧菜单包含项目。 单击这些项目后,我想在右侧面板上加载相应的用户控件(充当“子窗体”)。 我设法做到了这一点并且运作良好。

我担心的是我的用户控件是否正确处理,或者当用户单击另一个菜单项时它们是否保留在内存中(并因此加载另一个用户控件/子表单)。

代码与此类似:

    private void ultraExplorerBar1_ItemClick(object sender, Infragistics.Win.UltraWinExplorerBar.ItemEventArgs e)
    {
        panel1.Controls.Clear();

        if (e.Item.Key == "Action")
        {
            ActionUserControl subForm = new ActionUserControl();
            panel1.Controls.Add(subForm);
            subForm.Show();                
        }
        else if (e.Item.Key == "Options")
        {
            OptionsUserControl subForm = new OptionsUserControl();
            panel1.Controls.Add(subForm);
            subForm.Show();
        }
    }

我不确定我在方法开头调用的panel1.Controls.Clear()是否足以让不再使用的用户控件在适当的时候被垃圾收集?

根据我的理解,一旦从面板中清除,应用程序中不应该有任何参考,但我不确定我是否应该做其他事情或者我可以使用的相当轻量级的工具来确认我的子表单按它们应该处理,并且它不会导致某种内存/资源泄漏?

3 个答案:

答案 0 :(得分:6)

在调用panel1.Controls.Clear()之前使用此循环,并确保用户控件中的Dispose()方法依次处理任何可用资源。

foreach (Control control in panel1.Controls)
{
   control.Dispose();
}

答案 1 :(得分:4)

每个循环的A都不会完成这项工作。因为每次处理后元素和索引都会改变。

每次都需要一个while循环来处理最顶层的控件。

在我使用的以下代码中,我有一个包含用户控件的面板。 我进入第一个控件并处理它的控件然后处理控件本身。

在处理完所有控件后触发清除以重置索引。

While pnlMain.Controls.Count > 0

    While pnlMain.Controls(0).Controls.Count > 0
        pnlMain.Controls(0).Controls(0).Dispose()
    End While

    pnlMain.Controls(0).Dispose()
End While
pnlMain.Controls.Clear()

答案 2 :(得分:1)

我使用动态内容做了这个,我已将此方法添加到我的基页类:

/// <summary>
/// Dispose a control and all its children
/// </summary>
public void DisposeControl(Control c)
{
    if (null != c)
        using (c)
            DisposeChildControlsOf(c);
}

/// <summary>
/// Dispose (and remove) all the children of a control
/// </summary>
public void DisposeChildControlsOf(Control c)
{
    if (null != c)
        if (null != c.Controls)
            while (c.Controls.Count > 0)
            {
                Control child = c.Controls[0];
                c.Controls.RemoveAt(0);
                DisposeControl(child);
            }
}

它也是递归的。然后像这样调用它(如果你自己没有控件):

DisposeChildControlsOf(panel1);

DisposeControl(myDynamicallyGeneratedControl);