代表GC,我缺少什么? (我的委托是没有收集) [英] GC of delegates, what am I missing? (my delegate is not collected)

查看:121
本文介绍了代表GC,我缺少什么? (我的委托是没有收集)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有保存到一个代表一类,以便在以后懒洋洋地评估事情。

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:

  1. 不管DEBUG编译器,调试器附着,因为我创造了代表在一个单独的方法,这是我从返回,应该没有持有的委托,除了的WeakReference 延迟&LT; T&GT; 对象
  2. 如果我问延迟&LT; T&GT; 对象放弃其参考的委托,这将减少到只有一个引用是的WeakReference 持有到
  3. ,然后强制完整垃圾回收,假设,如果留下的唯一的参考是一个在的WeakReference
  4. 然后委托将被收集起来,而我的的WeakReference 将指示对象不再活着
  1. 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 the Lazy<T> objects
  2. If I ask the Lazy<T> object to relinquish its reference to the delegate, which would reduce the references to only the one that WeakReference is holding on to
  3. And then force a full garbage collection, assuming that if the only reference left is the one in WeakReference
  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆