3

在分析我的程序时,我注意到很多 byte[] 卡在内存中。我做了一些挖掘,发现大多数以某种方式创建的实例如下:

public byte[] CreateBytes(byte[] bytes)
{
    using (var start = new MemoryStream()) 
    {
        using (var memStr = new MemoryStream(bytes))
        {
            //do stuff
            return start.ToArray();
        }
    }
}

然后将返回的 byte[] 传递给其他方法,并用于MemoryStream从另一个 using 块中创建另一个:

using (var uncompressedStream = new MemoryStream(uncompressedData))
{
    using (var compressedStream = new MemoryStream())
    {
        //Do some compression
    }
}

myObject.Bytes = uncompressedData;
uncompressedData = null;

return myObject;

uncompressedData是从 CreateBytes() 返回的值)。

我的问题是,什么时候 byte[] 得到清理? 我是否特别需要将其设置为 null,如果需要,在哪里?在第二个 using 块之后,我不再需要它,但如果我简单地说uncompressedData = null;,我不确定这是否会回收内存。

我原以为 using 语句CreateBytes(byte[] bytes)会处理字节,但由于它返回引用,是否会推迟和/或放弃处理?

编辑:我添加了另一行代码。由于我将 uncompressedBtyes 存储在另一个对象中,将 uncompressedData 设置为 null 是没有意义的,并且 byte[] 将一直存在myObject(或直到myObject.Bytes设置为 null),对吗?

4

4 回答 4

5

当两个条件都满足时, byte[] 会被清理:

  • 没有对该内存块的引用
  • 垃圾收集器决定收集那个内存块

GC 基于各种因素在不确定的时间运行。

于 2012-08-29T20:53:42.920 回答
1

字节数组,就像内存中的任何其他托管对象一样,一旦不再可以从任何根引用访问,就有资格进行垃圾收集。您可以相信 GC 知道什么时候发生了这种情况,并智能地安排时间来实际清理合格的对象。尽量不要担心何时真正清理了符合清理条件的对象,GC 可能比你更清楚。

于 2012-08-29T20:55:10.590 回答
0

除了埃里克回答:

当您确定不再需要它byte[]时,分配给它null

这并不能保证内存现在会被回收,也不能保证之后会被回收,这只是一种帮助 GC识别它作为收集主题的方法。

于 2012-08-29T20:55:48.497 回答
0

该语句实际上与您返回using的数组无关。byte

是一次性的,并且该MemoryStream对象的处置是该using语句所管理的(请注意,处置与垃圾收集不同,但通常是其前身)。

当你打电话时ToArray(),你正在创造一些不是一次性的新东西;一旦超出范围,垃圾收集器将在不确定的时间对其进行清理(这通常是一个经过良好优化的过程)。

于 2012-08-29T20:57:35.897 回答