从使用块内返回一次性对象

时间:2012-08-29 20:51:53

标签: c# memory-management .net-4.0 memory-leaks using

我注意到很多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 (var uncompressedStream = new MemoryStream(uncompressedData))
{
    using (var compressedStream = new MemoryStream())
    {
        //Do some compression
    }
}

myObject.Bytes = uncompressedData;
uncompressedData = null;

return myObject;

uncompressedData是从CreateBytes()返回的值。

我的问题是,何时清除byte []?我是否需要将其设置为null,如果是,那么在哪里?在第二个使用块后我不再需要它,但如果我只是放uncompressedData = null;我不确定是否会回收内存。

我会认为CreateBytes(byte[] bytes)中的using语句会处理掉字节,但是因为它返回了一个引用会推迟和/或放弃处理吗?

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

4 个答案:

答案 0 :(得分:5)

当满足两个条件时,字节[]被清除:

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

GC根据各种因素在非确定性时间运行。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

除了Erics回答:

如果您确定不再需要byte[],请指定null

这不能保证现在将回收内存,也不会保证它会在之后重新回放,这只是一种帮助 GC识别的方法它就像一个收藏主题。

答案 3 :(得分:0)

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

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

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