为什么会出现内存泄漏的时候我不.Dispose()位图,我.Save()到一个MemoryStream?我不、位图、内存、时候

2023-09-04 04:23:15 作者:你的世界但愿都好

说我创​​建了一个位图

Say I create a Bitmap

Bitmap bitmap = new Bitmap(320, 200);

当我把它写一些流(对我来说,这是一个Htt的presponseStream,给出由HttpListenerResponse),一切都很好:

When I write it to some stream (in my case, it's a HttpResponseStream, as given out by HttpListenerResponse), everything is fine:

bitmap.Save(stream, ImageFormat.Png);

我不需要bitmap.Dispose(),所使用的位图的资源将得到自动清理。与直接写入一个巴到非可查找流的问题然而是,它可能会导致在GDI + ,这发生在我身上时,我试图在Azure上我的ASP应用程序时出现一般错误。所以这是我的code现在的外观:

I don't need to bitmap.Dispose(), the resources used by the bitmap will get cleaned up automatically. The problem with directly writing a Png to a non-seekable stream however is that it might result in A generic error occurred in GDI+, which happened to me when I tried my Asp app on Azure. So this is how my code looks now:

using (MemoryStream ms = new MemoryStream())
{
  bitmap.Save(ms, ImageFormat.Png);
  ms.WriteTo(stream);
}

现在,除非我bitmap.Dispose()之后,这会泄露。

Now unless I bitmap.Dispose() afterwards, this will leak.

改写的问题得到更具体的答案:的 为什么这个泄漏的位图的内存似乎取决于什么类型的流我将它保存到?

更新: 如果我敢肯定,这是一个泄漏,因为我一直在问的意见。多次拨打上述在压力测试中,我w3wp进程将上升到使用,直到我的机器开始交换音乐会和纪念音乐会,也不会清理。

Update: As I've been asked in comments if I'm sure it's a leak. Calling the above repeatedly in a stress test, my w3wp process will go up to gigs and gigs of memory used until my machine start swapping and it will not clean up.

推荐答案

Bitmap类使用的非托管资源。这些资源不与由存储器流类利用的资源。你可以只换了位图类using语句来处理位图实例,当你完成它。

Bitmap class utilizes unmanaged resources. These resources are not related to the resources utilized by the memory stream class. You can just wrap the bitmap class in a using statement to dispose of the bitmap instance when you are finished with it.

未接你问题的后半部分。到设置它和忘记它的一种方法是通过创建一个公开的位图实例,但实现了一个析构函数部署位图实例的包装类。该析构函数将意味着位图类的垃圾收集处置含蓄。

Missed the latter part of your question. One way to "set it and forget it" is by creating a wrapper class that exposes the bitmap instance but implements a destructor that disposes of the bitmap instance. This destructor will mean the bitmap class is disposed of implicitly at garbage collection.

最后要注意:您实例化实现IDisposable必须由code进行处理的对象。 Dipose将永远不会被隐式地调用。即使是在你的第一个例子。只是因为你的数据保存到流不MEAM内存已经然后被释放。大多数时候,它是为code表示实例化它在同一段内dipose的对象是一个好主意。这有助于更容易通过提高code透明度阅读code。

As a final note: Any object you instantiate that implements IDisposable MUST be disposed of by your code. Dipose will never be implicitly called. Even in your first example. Just because you save the data to a stream does not meam that memory has then been deallocated. Most of the time it is a good idea to dipose of an object within the same segment of code that instantiated it. This assists in easier to read code by boosting code transparency.