C#中相互引用的对象的垃圾收集

时间:2012-07-23 07:14:55

标签: c# garbage-collection weak-references

可以肯定之前已经问过这个问题,但我找不到任何有关此问题的帖子,所以链接到已回答的问题也会有所帮助:

我有一个包含切片(切片)数组的卷类(VoxelVolume)。

public class VoxelVolume
{
    Slice[] mySlices;

    public VoxelVolume(int noOfSlices)
    {
        mySlices = new Slice[noOfSlices];

        for (int i = 0; i < mySlices.Length; i++)
        {
            mySlices[i] = new Slice(this);
        }
    }
}

卷知道切片和切片知道卷:

public class Slice
{
    public VoxelVolume Volume
    {
        get;
        private set;
    }

    public Slice(VoxelVolume aVolume)
    {
        Volume = aVolume;
    }
}

问题是卷永远不会被垃圾收集,因为存在共同对象引用。出于这个原因,我将片段中的引用实现为WeakReference:

public class Slice
{
    WeakReference myVolume;

    VoxelVolume Volume
    {
        get
        {
            return (VoxelVolume)myVolume.Target;
        }
    }

    public Slice(VoxelVolume aVolume)
    {
        myVolume = new WeakReference(aVolume);
    }
}

现在垃圾收集工作正常,但需要额外的WeakReference。由于我可以拥有数千个切片,因此WeakReferences的工作量非常高。

编辑:首先它没有显示,但由于我们使用了大量内存,因此存在“内存泄漏”。因此,我们使用JetBrains dotTrace查看引用的和可用的对象。在那里我们已经看到很多物体可用,虽然它们不再使用了。正如我之前所说,使用WeakReference解决了这个问题。

问题是,TreeView如何解决这些问题,因为TreeNode也了解TreeView。

你知道一个合适的解决方案吗?

谢谢 马丁

2 个答案:

答案 0 :(得分:2)

  

问题是卷永远不会被垃圾收集,因为存在共同对象引用。

如果某事可以访问SliceVoxelVolume,那么这只会是一个问题。当您不再引用任何一个对象时,它们都有资格进行垃圾回收。对象中的循环在.NET中不是问题,因为它不使用引用计数。

当然,您需要确保没有来自任何GC根目的SliceVoxelVolume的引用。你还没有给我们足够的背景知道这里发生了什么。

答案 1 :(得分:0)

CLR中的GC引擎应该收集循环引用的对象,只要没有其他人引用它们中的任何一个。

当您决定不再需要它时,实现IDisposable模式并清除引用也是一个好主意。它可以减少大量内存泄漏的可能性,如果有什么不好的东西保留了你没注意到的引用。