如何强制收集MemoryStream的底层缓冲区?

时间:2013-09-12 13:58:57

标签: c# memory-management memory-leaks memorystream disposing

我正在使用内存流,但是我遇到了一些内存不足异常的问题。导致问题的方法如下。

public override T Deserialize<T>(byte[] source)
{
    using (var stream = new MemoryStream(source))
    {
        var result = (T)_formatter.Deserialize(stream);

        return result;
    }
}

这是对它的典型调用:

var bufferSize = binaryArrays.Sum(x => x.Length);
var streamBuffer = new byte[bufferSize];

using (var stream = new MemoryStream(streamBuffer))
{
    foreach (var binaryArray in binaryArrays)
    {
        stream.Write(binaryArray, 0, binaryArray.Length);
    }

    result = serializer.Deserialize<T>(stream.ToArray());
}

我在这个方法的包含类中实现了IDisposable,并且我明确地处理了流(即使它不是必需的)但是我无法回收我的记忆。据我所知,这是因为MemoryStream的底层缓冲区仍在浮动,我的应用程序的虚拟内存已经耗尽。那么,如何杀死底层缓冲区?我可以在这里使用任何技术吗?

非常感谢。

[编辑]

我修复了使用声明,但问题仍然存在。谢谢你。

2 个答案:

答案 0 :(得分:2)

将字节数组传递给MemoryStream构造函数时,该字节数组缓冲区。也许你仍然在调用代码中持有对该字节数组的引用?

您显示的代码不会保留数据(假设它实际分配本地变量,而不是分配给属性) - 并且处理流在这里肯定不重要,根本不会有帮助...... MemoryStream中的数据即使在处理完毕后也可用。

当然,如果您提供的代码非常准确,那么我建议您删除SerializerStream属性/字段。使用using语句重用现有属性/变量而不是声明新的局部变量,非常很少是一个好主意。

using (Stream stream = new MemoryStream(source))
{
    return (T) _formatter.Deserializer(stream);
}

答案 1 :(得分:0)

此部分似乎不正确使用(Stream = new MemoryStream(source)),您在哪里声明 Stream

如果您要将此变量排除在使用范围或方法之外,那么

来自using Statement (C# Reference)

  

您可以实例化资源对象,然后将变量传递给   使用声明但这不是最佳做法。在这种情况下,   控件离开使用块后,对象仍然在范围内   虽然它可能不再能够访问它的非托管   资源。换句话说,它将不再完全初始化。如果   你试图使用using块之外的对象,你冒险导致   被抛出的异常。出于这个原因,通常更好   在using语句中实例化对象并将其范围限制为   使用块。