我最近一直在使用DotSpatial库,并注意到我的程序严重泄漏了内存。我一直在使用VS内存诊断工具,并设法将问题缩小到以下(简化)代码块:
using (var inMemoryStream = new MemoryStream())
using (var _writer = new BinaryWriter(inMemoryStream))
{
WriteHeader(_writer);
_writer.Close();
}
BinaryWriter对象维护对inMemoryStream对象的引用,该对象分配给它的OutStream属性。似乎无论处理方法是什么(使用/ close / dispose),这个内存流都不会释放为它的缓冲区分配的内存。
我设法通过创建一个继承自BinaryWriter的类,重写Close()并在方法中添加“OutStream = null”来解决这个问题,但这看起来很笨拙。
我错过了什么吗? BinaryWriter是不是应该完全处理传递给它的流?似乎BinaryWriter.Close()确实试图对此效果做一些事情,因为使用intellisense查看OutStream的一些属性会显示ObjectDisposed异常。如果这有所不同,我正在使用.NET 4.5.2。
感谢您提前启发
答案 0 :(得分:2)
您似乎认为Dispose
意味着"清理引用"。有时可能就是这种情况,但Dispose
的实际目的是释放非托管资源。虽然Dispose
有许多用于其他目的的滥用(感谢方便的using
语法等),但您不应该期待更多。
关闭文件会释放非托管资源。关闭数据库连接会释放非托管资源。摆脱对另一个托管对象的引用?为什么你会期望这是Dispose
的一部分?在丢弃引用之前调用Dispose
- 无论如何都不能重复使用它,不能以任何方式使用已处置的对象。
当然,有些情况会导致内存泄漏。但在这种情况下,内存泄漏总是在那里 - Dispose
只能使更小。当然,这当然是值得的 - 但解决方案仍然只是解决问题并发布参考文献,而不是试图找到使泄漏资源量变小的方法。
答案 1 :(得分:2)
Dispose不会释放托管内存。这是垃圾收集器的工作。因此,虽然仍可从程序范围(即所有静态变量或当前本地)访问对MemoryStream的引用,但不会释放内存。
即使一旦MemoryStream不再被引用,它就会在内存释放时完全由GC决定。它不一定立即,甚至不久之后。这取决于其他因素,如整体记忆压力。