代表GC,我缺少什么? (我的委托是没有收集) [英] GC of delegates, what am I missing? (my delegate is not collected)
问题描述
我有保存到一个代表一类,以便在以后懒洋洋地评估事情。
I have a class that holds on to a delegate, in order to lazily evaluate something later.
在我评价它,通过调用委托,我清除掉参考代表,希望这将是符合回收。毕竟,它可能保存到本地变量的世界,如果它被构建为一个匿名方法。
Once I've evaluated it, by calling the delegate, I clear out the reference to the delegate, hoping that it would be eligible for collection. After all, it might hold on to a world of local variables if it was constructed as an anonymous method.
我试图构建一个单元测试来验证这一点,但它似乎并没有制定出我计划的方式,而不是好像,要么我对的WeakReference
假设(这是我用于测试目的这里),或一些其他的假设,是站不住脚的。
I tried building a unit-test to verify this, but it doesn't seem to work out the way I planned, instead it seems that either my assumptions about WeakReference
(which I used for test purposes here), or some other assumption, doesn't hold water.
看看这个code,您可以在 LINQPad
Take a look at this code, which you can run in LINQPad
void Main()
{
WeakReference wr;
Lazy<int> l;
CreateTestData(out wr, out l);
wr.IsAlive.Dump(); // should be alive here
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and alive here as well
l.Value.Dump(); // but now we clear the reference
GC.Collect(); // so one of these should collect it
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and then it should be gone here
GC.KeepAlive(l);
}
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
Func<int> f = () => 10;
wr = new WeakReference(f);
l = new Lazy<int>(f);
}
public class Lazy<T>
{
private Func<T> _GetValue;
private T _Value;
public Lazy(Func<T> getValue)
{
_GetValue = getValue;
}
public T Value
{
get
{
if (_GetValue != null)
{
_Value = _GetValue();
_GetValue = null;
}
return _Value;
}
}
}
我是假设是:
I was assuming that:
- 不管DEBUG编译器,调试器附着,因为我创造了代表在一个单独的方法,这是我从返回,应该没有持有的委托,除了
的WeakReference
和延迟&LT; T&GT;
对象 - 如果我问
延迟&LT; T&GT;
对象放弃其参考的委托,这将减少到只有一个引用是的WeakReference
持有到 - ,然后强制完整垃圾回收,假设,如果留下的唯一的参考是一个在
的WeakReference
- 然后委托将被收集起来,而我的
的WeakReference
将指示对象不再活着
- Regardless of DEBUG build, debugger attached, since I created the delegate in a separate method, which I return from, there should be nothing holding on to the delegate, except the
WeakReference
and theLazy<T>
objects - If I ask the
Lazy<T>
object to relinquish its reference to the delegate, which would reduce the references to only the one thatWeakReference
is holding on to - And then force a full garbage collection, assuming that if the only reference left is the one in
WeakReference
- Then the delegate would be collected, and my
WeakReference
would indicate that the object is no longer alive
的code的输出就这样预计(带注释):
The output of the code was thus expected to be (with comments):
true // not gc'ed after construction
true // not gc'ed after full GC, still beind held by Lazy<T>
10 // value from calling delegate
false // but is now gc'ed, Lazy<T> no longer has a reference to it
但是,相反的输出是:
But instead the output is:
true
true
10
true
任何人都可以提供一些线索上,我在这里失踪了什么?
Can anyone shed some light on what I'm missing here?
推荐答案
问题是,编译器已经注意到,它可以重复使用一个单一的委托实例的永远的。它没有捕获任何背景,甚至没有隐含的这
引用。所以这样的:
The "problem" is that the compiler is noticing that it can reuse a single delegate instance forever. It doesn't capture any context, not even the implicit this
reference. So this:
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
Func<int> f = () => 10;
...
}
变成是这样的:
Is turned into something like:
static Func<int> hiddenDelegate;
static int HiddenMethod()
{
return 10;
}
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
if (hiddenDelegate == null)
{
hiddenDelegate = HiddenMethod;
}
Func<int> f = hiddenDelegate;
...
}
看那code的反汇编(或反思,没有优化打开),看看到底发生了什么事情。
Look at the code in ildasm (or Reflector with no optimization turned on) to see exactly what's going on.
这篇关于代表GC,我缺少什么? (我的委托是没有收集)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!