2010-06-19 26 views
2

所以我在过去的一周里一直在处理我的项目中的另一个内存问题。我尝试了几个内存分析器,但没有让我知道是什么导致了小内存泄漏。下面的代码竟然是导致它:列表<T>。清除 - 是否需要调用?

private void DeleteAll(FlowLayoutPanel flp) 
{ 
    List<ImageControl> AllList = GetAllList(flp); 
    List<ImageControl> LockedList = GetLockedList(flp); 

    for (int i = 0; i < LockedList.Count; i++) 
    { 
     AllList.Remove(LockedList[i]); 
    } 

    flp.SuspendLayout(); 

    for (int i = 0; i < AllList.Count; i++) 
    { 
     flp.Controls.Remove(AllList[i]); 
    } 

    DisposeList(AllList); 

    flp.ResumeLayout(); 

} 

在代码中,ImageControl是一个用户控件,和上方的整个方法刚从FlowLayoutPanel的去除ImageControls的。 DisposList()方法为传递给它的列表中的所有控件调用ImageControl.Dispose()。现在

,我认为,一旦这种方法已经退出,AllList会超出范围,因此其所有的ImageControl的引用将是不存在的。所以GC会做这件事。但事实并非如此。我发现它需要

AllList.Clear(); 

在AllList超出范围之前,将其添加到DeleteAll()方法的末尾。

所以你必须始终明确地清除泛型列表,以腾出资源?或者是我在上面做错了什么?我想知道,因为我在这个项目中大量使用临时列表。

好吧,这里的GetAllList方法。看起来并不像一个问题,我说:

private List<ImageControl> GetAllList(FlowLayoutPanel flp) 
{ 
    List<ImageControl> List = new List<ImageControl>(); 

    for (int i = 0; i < flp.Controls.Count; i++) 
    { 
     List.Add((ImageControl)flp.Controls[i]); 
    } 

    return List; 
} 

顺便说一句,如果你看到我过去的几个主题在这里,我一直在争取的内存泄漏我的追求,成为一个精通C#程序员:)我增加了DisposeList ()方法,因为我已经阅读Dispose()应该在实现IDisposable的任何对象上调用,而UserControl会这样做。我还需要一种方法来修复ToolStrip类(ImageControl包含的)的“bug”,它会导致资源保留,除非Visible属性在其销毁之前设置为false。所以我重写了ImageControl的Dispose方法来做到这一点。

private void DisposeList(List<ImageControl> IC) 
{ 
    for (int i=0;i<IC.Count;i++) 
    { 
     IC[i].DoEvent -= ImageButtonClick; 
     IC[i].Dispose(); 
    } 
} 
+3

注意这里是“减名单”一个更加简洁和更清晰的方式:'VAR减去= listA.Except(数组listB);' (这需要'使用System.Linq') – 2010-06-19 22:25:19

回答

4

如果AllList是到列表仅作参考,在列表中的元素,则列表和它的所有元素才有资格:

哦,DisposeList()也从一个事件处理退订只要您退出DeleteAll方法即可进行垃圾回收。

如果调用AllList.Clear()有差别,那么我会得出这样的结论相同的列表的引用代码中的其他地方举行。也许仔细看一下GetAllList()方法会给出一个线索。

1

你不应该清除列表。你能分享你的GetAllList()函数吗?事实上,你甚至需要一个相应的“DisposeList()”方法告诉我,那里可能有副作用,在某处保留对你的列表的引用。

另外,我想简化代码:

private void DeleteAll(FlowLayoutPanel flp) 
{ 
    var UnlockedImages = flp.Controls.OfType<ImageControl>().Except(GetLockedList(flp)); 

    flp.SuspendLayout(); 

    foreach (ImageControl ic in UnlockedImages) 
    { 
     flp.Controls.Remove(ic); 
    } 

    flp.ResumeLayout(); 
} 
相关问题