所以我过去一周在我的项目中遇到了另一个内存问题。我尝试了几个内存分析器,但没有什么能让我深入了解导致次要内存泄漏的原因。以下代码证明了它的原因:
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是一个UserControl,上面的整个方法只是从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方法来做到这一点。
哦,DisposeList()也取消订阅事件处理程序:
private void DisposeList( List<ImageControl> IC )
{
for (int i=0;i<IC.Count;i++)
{
IC[i].DoEvent -= ImageButtonClick;
IC[i].Dispose();
}
}
答案 0 :(得分:4)
如果AllList
是对列表和列表中元素的唯一引用,那么一旦退出DeleteAll
方法,列表及其所有元素就有资格进行垃圾回收。< / p>
如果调用AllList.Clear()
会产生影响,那么我会得出结论,在代码中的其他地方存在对相同列表的引用。也许仔细看看GetAllList()方法会给出一个线索。
答案 1 :(得分: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();
}