列表对象的垃圾收集



我想问一下清洁的效率和处理列表中的对象的效率是什么?

是通过调用list.clear()方法将自动清洁其收集的所有对象?

例如,请考虑以下示例

public partial class Form1 : Form
{
    FontCollection m_fontCollection;
    public Form1()
    {
        InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        m_fontCollection = new FontCollection();
        for (int i = 0; i < 5000; i++)
        {
            Font font = new Font("Arial", 23);
            FontImpl impl = new FontImpl(font, Color.Black);
            impl.AfterChange += 
                new FontImpl.AfterChangeHandler(impl_AfterChange);
            m_fontCollection.Add(impl);
        }
        m_fontCollection.Dispose();
        MessageBox.Show("TakeSnap");
    }
    void impl_AfterChange()
    {
        throw new NotImplementedException();
    }
}
public class FontCollection : IEnumerable, IDisposable
{
    IList<FontImpl> m_Implementation = new List<FontImpl>();
    internal void Add(FontImpl impl)
    {
        this.m_Implementation.Add(impl);
    }
    public IEnumerator GetEnumerator()
    {
        return this.m_Implementation.GetEnumerator();
    }
    public void Dispose()
    {
        m_Implementation.Clear();
        m_Implementation = null;
    }
}
public class FontImpl
{
    private Font m_Font;
    private Color m_color;
    public FontImpl(Font newFont, Color newColcor)
    {
        m_Font = newFont;
        m_color = newColcor;
    }
    public event AfterChangeHandler AfterChange;
    public delegate void AfterChangeHandler();
}

当我运行上述应用程序蚂蚁内存profiler时,我可以看到内存泄漏字体和fontfamily(我无法上传屏幕)以及如何删除这些泄漏

通常,您不需要担心垃圾收集,以及何时发生垃圾。当对其参考为零时,一个对象有资格使用GC。

应该注意的是IDisposable对象。使用IDisposable对象完成后,您确实需要在其上调用Dispose()。如果对象生活在函数函数的本地范围内,则using块使它变得容易:

using (var resource = new SomeIDisposable()) {
    // use resource
    // resource.Dispose() is automatically called, *even if* an exception
    // is thrown.
}

you can 通过以"悬空引用"对象导致内存泄漏,这阻止了它们被收集到垃圾。最常见的原因是事件处理程序。当您订阅对象A暴露的事件时,在对象B上使用事件处理程序,A将引用B

class B {
    void hook_up_to(A a) {
        a.SomeEvent += Handler;     // `a` gets a reference to `this`
    }
    void Handler(object sender, EventArgs e) {
    }
}
class Program {
    private A _a = new A();
    static void SomeMethod() {
        var b = new B();
        b.hook_up_to(_a);    // _a now has a reference to b
        // b goes out of scope.
    }
}

通常,当b脱离范围时,它引用的对象将符合垃圾收集的条件。但是,在这种情况下,b连接到成员变量_a发布的事件,这导致_a获得了对b的参考。现在,有一个对b的出色引用,这是不可能的 1 可以清除的,而b不合格GC。这是一个内存泄漏。

1 在这种情况下,唯一的参考b的方法是this指针,如果/触发事件处理程序时。

您无需在课堂上实现IDisposable。通常,您的课程唯一需要实现IDisposable的时间是需要处理其他类时(数据库和网络连接之类的东西,以及不受管理的对象)。

在您的示例中,您可能需要考虑在button1_Click中制作m_fontCollection A local 变量,因为您正在完全在该方法中创建和处置它。如果您将其定为本地,则一旦button1_Click退出.../div>

clear只需从列表中删除所有内容即可。在您的情况下,您有一个可iDisposable对象的列表,需要在列表中的所有项目上调用Distose。呼叫Clear不会做到这一点。

您的fontimpl应该实现Idisposable,因为它可以管理一个可iDisposable的对象:

 public void Dispose() {
      if (m_Font != null) {
          m_Font.Dispose();
          m_Font = null;
      }
 }

,您的fontcollection处置应该像这样:

public void Dispose()
{
    foreach(FontImpl font in m_Implementation) {
        font.Dispose();
    }
    m_Implementation.Clear();
    m_Implementation = null;
}

在您显示的代码的情况下,您具有实现IDisposableFont对象,因此应处置。这些对象由您的FontImpl类管理,因此FontImpl应实现IDisposable。您的FontCollection类包含一个FontImpl对象的列表,该对象现在应该是可置的,因此FontCollection需要实现IDisposable

您应该阅读有关Idisposable模式的阅读(因此,此答案提供了一些很棒的信息-https://stackoverflow.com/a/538238/416574)。

话虽如此,从您提供的代码片段中,您似乎没有从FontCollection获得任何东西以包装列表。除非您还将与该类别做其他事情,否则我只会有一个列表作为成员变量。这样,在您表格的Dispose方法中,您可以步行列表并处理FontImpl对象。如果您想保护双重处理,请在处置所有内容后清空清单。

相关内容

  • 没有找到相关文章

最新更新