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



当然这个问题以前也被问过,但我找不到任何关于这个问题的线索,所以链接到一个已回答的问题也会很有帮助:

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

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。

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

谢谢Martin

问题是,由于存在相互的对象引用,卷永远不会被垃圾收集。

只有当something能够访问SliceVoxelVolume时,这才是一个问题。当您不再有对任一对象的引用时,它们都将有资格进行垃圾回收。对象中的循环在.NET中不是问题,因为它不使用引用计数。

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

CLR中的

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

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

相关内容

  • 没有找到相关文章

最新更新