是否可以使用反射修改ReadOnlyCollection

时间:2011-03-08 19:56:20

标签: c# reflection garbage-collection readonly-collection

我正在处理一个SDK,它会保留对它创建的每个对象的引用,只要主连接对象在范围内。定期创建新的连接对象会导致其他资源问题,而且不是一个选项。

要做我需要做的事情,我必须遍历数千个这些对象(差不多100,000个),虽然我当然不会保留对这些对象的引用,但我正在使用的SDK中的对象模型确实如此。这会掠过内存,并且危险地接近导致OutOfMemoryExceptions。

这些对象存储在嵌套的ReadOnlyCollections中,所以我现在正在尝试的是,当我完成它们时,使用反射将这些集合中的一些设置为null,这样垃圾收集器就可以收集用过的内存。 / p>

foreach (Build build in builds)
{
        BinaryFileCollection numBinaries = build.GetBinaries();
        foreach (BinaryFile binary in numBinaries)
        {
            this.CoveredBlocks += binary.HitBlockCount;
            this.TotalBlocks += binary.BlockCount;
            this.CoveredArcs += binary.HitArcCount;
            this.TotalArcs += binary.ArcCount;

            if (binary.HitBlockCount > 0)
            {
                this.CoveredSourceFiles++;
            }

            this.TotalSourceFiles++;

            foreach (Class coverageClass in binary.GetClasses())
            {
                if (coverageClass.HitBlockCount > 0)
                {
                    this.CoveredClasses++;
                }

                this.TotalClasses++;

                foreach (Function function in coverageClass.GetFunctions())
                {
                    if (function.HitBlockCount > 0)
                    {
                        this.CoveredFunctions++;
                    }

                    this.TotalFunctions++;
                }
            }

            FieldInfo fi = typeof(BinaryFile).GetField("classes", BindingFlags.NonPublic | BindingFlags.Instance);
            fi.SetValue(binary, null);
    }

当我在numBinaries [0]中检查类成员的值时,它返回null,这似乎完成了任务,但是当我运行此代码时,内存消耗不断上升,就像我一样快不要将类设置为null。

我想弄清楚的是,这种方法中是否存在一些本质上存在缺陷的东西,或者是否有另一个对象保留了对我缺少的类ReadOnlyCollection的引用。

1 个答案:

答案 0 :(得分:0)

我可以想到一些替代方案......

  1. 逻辑上拆分出来。你提到它保留所有引用“在连接期间”。你可以做10%,关闭它,开一个新的,跳过10%,再拿10%(总共20%)等吗?
  2. 我们在这里谈论了多少内存,这个工具是否会长寿?那么如果它在几分钟内使用大量内存呢?你真的得到OOM吗?如果您的系统有足够的可用RAM供程序使用,为什么不使用它?你支付了RAM。这让我想起了Raymond Chen的blog posts大约100%的CPU消耗。
  3. 如果你真的想知道什么能阻止收集垃圾,那么启动SOS并使用!gcroot就可以了。
  4. 但尽管如此,如果这真的是一个问题,我会花更多的时间与第三方API提供商 - 在某些时候他们可能会发布你想要的更新打破这个 - 你会回到原点一个或者更糟,你可以在产品中引入微妙的错误。