我想要回忆我的记忆!我怎样才能真正处置控件?

7 c# memory controls dispose collect

我有一个我正在制作的应用程序,它创建了大量的窗口控件(按钮和标签等).它们都是通过功能动态制作的.我遇到的问题是,当我删除控件并处理它们时,它们不会从内存中删除.

void loadALoadOfStuff()
{
    while(tabControlToClear.Controls.Count > 0)
        tabControlToClear.Controls[0].Dispose();
    //I even put in:
    GC.Collect();
    GC.WaitForPendingFinalizers();
    foreach(String pagename in globalList)
        tabControlToClear.Controls.Add(MakeATab(pagename));
}

TabPage MakeATab(string tabText)
{
    TabPage newT = new MakeATab();
    newT.Text = tabText;
    //Fill page with controls with methods like this
    return newT;
}
Run Code Online (Sandbox Code Playgroud)

现在由于某种原因,这只是没有给我回忆,所以当进程运行5次时,我最终会出现内存不足的情况.我是对象和控制处置的新手,但是通过庞大的网络查看仍然没有给我任何指示,所以如果你们有任何想法,我会很高兴听到它.

更新:我一直在关注用户对象的创建和销毁(taskmanager),并注意到我创建了一个标签页,添加了一个单击处理程序,添加了一个面板,添加了两个按钮,包括点击处理程序,工具提示和背景图像(我认为这是哪里问题是).该应用程序说它创建了8个新项目,但是当我运行我的处理时,我只从内存中删除4个.我一直试图删除事件处理程序,但似乎没有任何区别.

解决!!!当我向面板添加新项目时,我向他们传递了一个工具提示(愚蠢,但我正在学习).对于其他任何有同样问题的人,(感谢下面的人的评论和指示.我发现为了让控件真正处理掉(因为我意识到我错误地把它放了)是:

1:如果你有工具提示,请确认它是可以访问的!不要做我想做的事!例如:

这是错的!

TabPage MakeATab(string tabText)
{
    TabPage newT = new MakeATab();
    ToolTip myTip = new ToolTip();
    newT.Text = tabText;
    //Fill page with controls with methods like this
    myTip.SetToolTip(newT, "Something to say");
    return newT;
}
Run Code Online (Sandbox Code Playgroud)

如果你这样做,你将失去指向工具提示的指针,并且因为工具提示不是它所连接的对象的子节点(相反,工具提示强烈引用控件),那么即使你破坏了控件,您无法访问的工具提示可使对象保持活动状态.

2:在任何事情之前,调用toolTip.RemoveAll().这将删除它与控件的所有联系.请注意,如果您将此提示用于其他控件,他们只是丢失了他们的工具提示.

3:从基本control.ControlCollection中删除任何内部控件(如果他们使用非托管内存,我猜.我正在这样做,因为它使我的应用程序正常工作......)

4:删除任何自定义事件处理程序.

5:最后,配置对象.我做了一个快速递归功能,它做得很好.

    private void RecursiveDispose(Control toDispose)
    {
        while (toDispose.Controls.Count > 0)
            RecursiveDispose(toDispose.Controls[0]);

        if (toDispose.BackgroundImage != null)
            BackgroundImage = null;

        if (toDispose.GetType() == typeof(Button))
            toDispose.Click -= [Your Event];
        else if (toDispose.GetType() == typeof(TabPage))
            toDispose.DoubleClick -= [Your Event];
        else if (toDispose.GetType() == typeof(Label))
            toDispose.MouseMove -= [Your Event];

        toDispose.Dispose();
    }
Run Code Online (Sandbox Code Playgroud)

这是非常粗糙的,并且可能有更好的方法,但除非有人能提出它,否则必须这样做.谢谢大家的帮助.您可能刚刚保存了我的整个项目.

Cha*_*ion 6

您还需要清除参考.

while(tabControlToClear.Controls.Count > 0)
{ 
    var tabPage = tabControlToClear.Controls[0];
    tabControlToClear.Controls.RemoveAt(0);
    tabPage.Dispose(); 

    // Clear out events.

    foreach (EventHandler subscriber in tabPage.Click.GetInvocationList())
    {
        tabPage.Click -= subscriber;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 也许"tabPage.Dispose();" 应该在分离事件处理程序后调用? (5认同)