C# 弱引用的使用

C# WeakReference use

所以,我有一个这样的 class。 (对不起,如果有人问过这个问题,因为它看起来很笼统)

    public class Parent{

        private Child child1, child2;

        void someFunc(){
            child1 = new Child ();
            child2 = new Child ();
            child1.handle += parentHandle;
            child2.handle += parentHandle;
        }

        void parentHandle (Child sender)
        {
            Console.WriteLine ("Sender is: " + sender.ToString ());
        }
    }

    public class Child{

        public OnHandle handle;
        delegate void OnHandle(Child sender);

        void someChildFunc(){
            handle (this);
        }

    }

父项引用了子项,子项引用了父项的处理程序。这是循环内存泄漏吗?我应该使用弱引用吗?

经典的 WeakReferencing 用于相对较大的内存对象,这些对象创建起来并不耗时。通过 weak-referencing 这样的对象,我们让 GC 知道尽管有活动引用,也可以清除;如果再次调用引用的对象,则会再次创建它。这是博客 link 。好处是避免占用您的内存并将其用于其他内容,并且当再次使用弱引用时,它会再次创建(这可能必须很快)。

Whosebug post解释了为什么它不会导致内存泄漏(即使可能存在循环引用)。

以下是使用您的父子 类 并创建一个巨大的演示对象然后将其设置为 null 的代码片段。该过程重复三次,并在不同阶段测量记忆力。初始内存碰撞后,所有其他 pre-creation post-creation 和 post-null 读数不会改变,这意味着没有内存泄漏!

    class Program
{
    static void Main(string[] args)
    {
        MonitorMemoryUsage();
        MonitorMemoryUsage();
        MonitorMemoryUsage();


        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

    private static void MonitorMemoryUsage()
    {
        DisplayMemoryAfterGc("Before creation");
        var demonstrator = new Demonstrator();

        DisplayMemoryAfterGc("After creation");

        if (demonstrator.Children != null && demonstrator.Children.Count > 0)
        {
            demonstrator.Children = null;
            demonstrator.Parents = null;
            demonstrator = null;
        }


        Console.WriteLine(demonstrator == null);
        DisplayMemoryAfterGc("After null");
    }

    private static void DisplayMemoryAfterGc(string eventType)
    {
        GC.Collect();
        GC.WaitForFullGCComplete();
        var totalMemory = GC.GetTotalMemory(true);
        Console.WriteLine(eventType + ":" + totalMemory);
    }
}

public class Demonstrator
{
    public List<Parent> Parents { get; set; }
    public List<Child> Children { get; set; }

    public Demonstrator()
    {
        Parents = new List<Parent>();
        Children = new List<Child>();

        for (int i = 0; i < 10000; i++)
        {
            var parent = new Parent();

            Parents.Add(parent);

            Children.Add(parent._child1);
        }
    }

}

public class Parent
{

    public Child _child1, _child2;

    void someFunc()
    {
        _child1 = new Child();
        _child2 = new Child();
        _child1.handle += parentHandle;
    }

    void parentHandle(Child sender)
    {
        Console.WriteLine("Sender is: " + sender.ToString());
    }
}

public class Child
{

    public OnHandle handle;

    public delegate void OnHandle(Child sender);

    void someChildFunc()
    {
        handle(this);
    }

}