2010-06-19 25 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(); 
} 
相關問題