【问题标题】:Memory leak - Returning without disposing "new CheckBox(...)"内存泄漏 - 返回而不处理“new CheckBox(...)”
【发布时间】:2012-11-21 10:38:22
【问题描述】:
protected override void SetValueFromControl()
{
CheckBox checkbox = new CheckBox();

if (this.comboBox_Meta.SelectedItem != null)
{
    if (this.comboBox_Meta.SelectedIndex != 1)
    {
        checkbox.Checked = true;
    }
    else
    {
       checkbox.Checked = false;
    }

    this.my_Helper.SetValueFromCheckBox("xxx", checkbox);
}
}

我的 ANT Profiler 说有资源泄漏,如下错误

返回而不处理“new CheckBox(...)”。

在我的 SetValueFromCheckBox 方法中,我使用以下条件。

some value = _checkbox.Checked;

注意:现在在社区提供有用的反馈后,我添加了“使用”并等待下一次构建以进行错误验证。

【问题讨论】:

  • 除非SetValueFromCheckBox 这样做,否则为什么要创建CheckBox 而不将其添加到表单中?
  • 您创建了一个复选框,但没有将其添加到控件树中。您的代码是不是缺少某些部分?
  • 另外请添加 [asp.net]、[winform] 或 [WPF] 标签!
  • iShare,您还没有回答 Steve B 的问题。我们知道您正在使用该对象及其属性,但可以改用布尔变量重写代码。创建 CheckBox UI 控件的必要性是什么?

标签: c# winforms memory-leaks


【解决方案1】:

不,错误意味着您应该调用Dispose

或将其包装在 using 块中:

using (var chk = new CheckBox())
{
    // your code
} // at this line `Dispose` is called automatically, even in case of exception

每个 Windows 窗体控件都会创建一堆不会自动释放的句柄等。它们中的大多数仅在显示控件时创建,因此您可能没有 dispose 调用就可以了,但因为探查器不知道它会抱怨。最好的做法是始终处置实现 IDisposable 的对象 - 您永远不知道实现是否会更改,并且对象会自行创建句柄。

文档:http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

【讨论】:

  • 这段代码没有意义......如果不使用复选框,为什么要创建一个复选框?这无助于 OP 理解它发生的原因。它只会掩盖一个真正的问题
  • @SteveB:不要投反对票 - 查看 OP 的源代码。此外,从 Knagis 的代码中甚至不清楚该复选框是否未使用。在using 块内,它可能会被正确使用。
  • +1 用于解释 Dispose 模式,但我认为仍然是无效的答案
【解决方案2】:

一个常见的误解是,将事物设置为 null 实际上会处理它们。它不是。要处理CheckBox,请调用其Dispose 方法。当您按照其他人的建议使用 using 语句时,这会自动完成。

但是,当您实际将控件添加到控件树时,这不是必需的!在这种情况下,控件将在表单被释放时被释放。

【讨论】:

    【解决方案3】:

    这意味着你应该对它调用 dispose 或使用 using 语句。

    using(CheckBox checkbox = new CheckBox())
    {
    
        if (this.comboBox_Meta.SelectedItem != null)
        {
            if (this.comboBox_Meta.SelectedIndex != 1)
            {
                checkbox.Checked = true;
            }
            else
            {
               checkbox.Checked = false;
    
            }
    
            this.my_Helper.SetValueFromCheckBox("xxx", checkbox);
        }
    }
    

    【讨论】:

    • 这是 OP 发布的代码。我只是将它包装在一个 using 块中。在此调用中还使用了 checkbox 变量 'this.my_Helper.SetValueFromCheckBox("xxx", checkbox);'
    • @SteveB:根据 OP 的代码对人们投反对票是不公平的。
    • 我认为你的回答会造成更多的损害而不是帮助。删除警告并不意味着问题已解决。我真的相信 OP 应该以正确的方式而不是隐藏问题。
    • 我相信修复不仅针对警告,而且还处理在代码中创建的控制对象。 OP 是否选择将此添加到他们的 UI 控件树中,是他们的选择,也取决于逻辑。仅仅因为我认为应该将控件添加到表单中并不意味着这是唯一正确的方法。
    【解决方案4】:

    当您创建动态控件时,您最终应该将控件添加到控件树中。

    如果你不这样做,那么创建这样的控制是没有意义的。

    不将控件添加到树控件的直接副作用是您将错过控件树的开箱即用处置。当一个控件被释放时(顶层的窗体),它的子控件将被递归释放。

    其他人建议添加using 声明,但我认为这是错误的。它将删除警告,但实际问题是您没有正确使用控件树。

    【讨论】:

    • 如果用户只想在代码中使用控件而不显示它怎么办?在这种情况下,用户需要在没有将其添加到表单或其中的任何控件的情况下显式处理它?
    • 对于要在其他地方使用的控件对象...可能是一个类库需要一个 UI 控件类型的对象,我可能没有写过(写得不好和接口库)但是我需要将它用于我当前的应用程序。
    • 不要忘记,即使 IF SetValueFromCheckbox 会对 Checkbox 做一些有用的事情,但并非所有代码路径都可以使用它...
    • 如果 OP 证明这一决定是合理的,我将删除反对票。让他有机会理清思路
    • 谢谢史蒂夫,我会编辑我的帖子并提供更多信息
    猜你喜欢
    • 2013-11-10
    • 2015-06-14
    • 2013-05-25
    • 1970-01-01
    • 2016-07-07
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    相关资源
    最近更新 更多