今天在分析项目内存释放和垃圾回收问题的时候,注意到了一个问题,如果一个变量被闭包引用,则不会被垃圾回收掉(这理论上是废话),这正是这样,这个问题才变得很难查。这意味着,一些按钮绑定了带闭包的事件,这部分内存就很难回收了。可以看一个例子:
public class B
{
public int Name;
}
class TestClass
{
private Action action;
private static WeakReference<B> weak;
public void GenerateClosure()
{
B b = new B();
weak = new WeakReference<B>(b);
action = () =>
{
Console.WriteLine(b.Name);
};
}
public void ReleaseClosure()
{
action = null;
}
public void OverWatchGC()
{
if (weak.TryGetTarget(out B b))
{
Console.WriteLine("B未被回收");
}
else
{
Console.WriteLine("B被回收了");
}
}
}
class Program
{
public static void Main(string[] args)
{
TestClass c = new TestClass();
c.GenerateClosure();
GC.Collect();
c.OverWatchGC();
c.ReleaseClosure();
GC.Collect();
c.OverWatchGC();
}
}
结果如下:
B未被回收
B被回收了
如果闭包所在的函数是静态函数,则回收还会更麻烦,我在测试中,即便把action置为null,垃圾回收也没有成功回收掉对B的引用。
所以要谨慎谨慎再谨慎,有时候一个小点累积下去,就是一个非常难排查的问题
搜索
复制