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);
}
}
所以,我有一个这样的 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);
}
}