【发布时间】:2011-03-08 19:56:19
【问题描述】:
我正在处理一个 SDK,它保留对它创建的每个对象的引用,只要主连接对象在范围内。定期创建新的连接对象会导致其他资源问题,这不是一种选择。
要完成我需要做的事情,我必须遍历数千个这样的对象(几乎 100,000 个),虽然我当然不会保留对这些对象的引用,但我正在使用的 SDK 中的对象模型会这样做。这会消耗内存并且非常接近导致 OutOfMemoryExceptions。
这些对象存储在嵌套的 ReadOnlyCollections 中,所以我现在正在尝试使用反射将其中一些集合设置为空,当我完成它们时,垃圾收集器可以收集使用的内存。
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 的引用。
【问题讨论】:
-
你试过反射器来看看你的 API 到底在做什么。只读集合只是对读/写集合的引用。所以除非你能找到源头,否则它(可能)是行不通的。我假设您已经尝试过您的 SDK 供应商
-
我一直在使用反射器查看 SDK,这就是我对私有类字段的了解。我认为如果我使包含对只读集合的引用的对象为空,那么 GC 将看到只读集合没有对它的引用,并且它的内部列表没有引用并清理堆起来。
-
“我现在正在尝试使用反射将其中一些集合设置为空”——几乎可以肯定是错误的/解决这个问题的最坏方法。也就是说,即使从字面上看,这个问题也太宽泛了,因为它完全取决于集合的使用方式,甚至它们到底是什么集合类。实际上,这应该是一个不同的问题,特别是关于如何处理有问题的库及其过多的内存需求。使用反射处理只读集合肯定会遇到麻烦
标签: c# reflection garbage-collection readonly-collection