在我看来,当我在对象类的委托方法上使用WeakReference
类时,对象类会被GC收集,但是还有另一个副本驻留在{{1}中}?
我发现用文字解释很难。我举个例子。我有以下名为WeakReference
的对象类:
TestObject
现在,在我的主应用程序中,我尝试通过class TestObject
{
public string message = "";
private delegate string deleg();
public TestObject(string msg)
{
message = msg;
}
public Delegate GetMethod()
{
deleg tmp = this.TestMethod;
return tmp;
}
public string TestMethod()
{
return message;
}
}
引用TestMethod
中的方法TestObject
。目的是当所有硬引用都消失时,GC可以收集WeakReference
。这就是我的主要应用程序的样子:
TestObject
这是我运行上述代码时的输出:
这是奇怪的事情。 在第一行,static void Main(string[] args)
{
var list = new List<WeakReference>();
var obj = new TestObject("Hello 1");
list.Add(new WeakReference(obj.GetMethod()));
Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke()); //Works fine
obj = null; //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC
GC.Collect(); //Force GC
Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False"));
Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke());
Console.ReadKey();
}
可以打印obj
,因为它刚刚初始化,"Hello 1"
持有对obj
的引用。全对了。接下来,TestObject
设置为obj
null
,GC被迫收集。因此,在输出的第二行中,obj = null
为obj
为空。最后在最后一行,因为GC收集了true
,我希望它能抛出obj
或者只输出输出。但是,它实际上打印的内容与输出的第一行相同!此时GC不应该收集NullReferenceException
吗?!
在我将obj设置为null之后,如果TestObject
中首次保存的TestObject
后来被GC收集了,那么这就引出了一个问题。
如果我将整个对象传递到obj
,即WeakReference
,而不是委托进入new WeakReference(obj)
,那么它将完美地运行。
不幸的是,在我的代码中,我需要传递给WeakReference
代理人。如何使WeakReference
正常工作,以便GC只能通过引用委托来收集对象?
答案 0 :(得分:6)
我认为问题出在你的测试中 - 而不是在框架中。似乎将局部变量设置为null并不能达到预期效果。如果我们完全跳过局部变量,我们在'after'行得到预期的NullReferenceException:
static void Main(string[] args)
{
var list = new List<WeakReference>();
//var obj = new TestObject("Hello 1");
list.Add(new WeakReference(new TestObject("Hello 1").GetMethod()));
Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke()); //Works fine
//obj = null; //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC
GC.Collect(); //Force GC
//Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False"));
Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke());
Console.ReadKey();
}
答案 1 :(得分:0)
实际上你的例子会按预期运行,因为除了WeakReference引用了Delegate之外什么都没有,所以GC可以收集它,即使你注释掉“obj = null”行!
也许是因为我在一个独立的线程上运行代码(除主线程外)?