当前位置:网站首页>C# 闭包的垃圾回收

C# 闭包的垃圾回收

2022-06-24 19:50:00 Moyiii

今天在分析项目内存释放和垃圾回收问题的时候,注意到了一个问题,如果一个变量被闭包引用,则不会被垃圾回收掉(这理论上是废话),这正是这样,这个问题才变得很难查。这意味着,一些按钮绑定了带闭包的事件,这部分内存就很难回收了。可以看一个例子:

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的引用。

所以要谨慎谨慎再谨慎,有时候一个小点累积下去,就是一个非常难排查的问题

原网站

版权声明
本文为[Moyiii]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Moyiii/article/details/125415828