Image PropertyItems and disposed MemoryStream

时光总嘲笑我的痴心妄想 提交于 2019-12-13 16:14:41

问题


I'm loading an Image from a byte[] using MemoryStream and getting information about the image by inspecting it's ProperyItems. In the process of doing this though, I noticed some odd behaviour where some of the image's PropertyItems were disappearing. After much debugging I finally figured out that this was being caused by the MemoryStream being disposed.

MemoryStream ms0 = new MemoryStream(imageBytes);
Image img0 = Image.FromStream(ms0);
Console.Out.WriteLine("Without using, Image propertyIDs: ");
foreach (int itemId in img0.PropertyIdList)
    Console.Out.Write(itemId + ", ");
Console.Out.Write("\n");

Image img1 = null;
using (MemoryStream ms1 = new MemoryStream(imageBytes))
{
    img1 = Image.FromStream(ms1);
}
Console.Out.WriteLine("Outside using, Image propertyIDs: ");
foreach (int itemId in img1.PropertyIdList)
    Console.Out.Write(itemId + ", ");
Console.Out.Write("\n");

Output:

Without using, Image propertyIDs: 
254, 256, 257, 258, 259, 262, 269, 273, 274, 277, 278, 279, 282, 283, 284, 296, 
Outside using, Image propertyIDs: 
254, 256, 257, 258, 259, 262, 274, 277, 278, 284, 296, 

So it appears that at least some of the PropertyItems are directly backed by the contents of the MemoryStream and the solution is not to dispose it, or am I wrong?

In the process of debugging this issue though I've noticed something else odd, if I access the PropertyIdList (or anything related to the images PropertyItems) inside the using block, the PropertyItems won't disappear after the MemoryStream is disposed.

Image img2 = null;
using (MemoryStream ms2 = new MemoryStream(imageBytes))
{
    img2 = Image.FromStream(ms2);
    int[] tmp = img2.PropertyIdList;
}
Console.Out.WriteLine("Outside using with PropertyIdList access, Image propertyIDs: ");
foreach (int itemId in img2.PropertyIdList)
    Console.Out.Write(itemId + ", ");
Console.Out.Write("\n");

Output:

Outside using with PropertyIdList access, Image propertyIDs: 
254, 256, 257, 258, 259, 262, 269, 273, 274, 277, 278, 279, 282, 283, 284, 296,

I looked at the source for the Image class and the PropertyIdList property doesn't appear to be retaining a local copy of the PropertyItems data, so why are the PropertyItems retained after the MemoryStream is disposed in this situation?


回答1:


Disposing a MemoryStream is in general a fairly useless thing to do. It doesn't have any disposable resources itself, it is just memory and that's already managed by the garbage collector. It only matters if you've used the BeginRead/Write() methods and they are not yet completed, something you just never do.

It does however set the CanRead() property to false. And that's quite lethal to the Bitmap object you loaded from the MemoryStream.

What happens next, when you keep using the Bitmap, is fairly unpredictable. GDI+ requires that the stream stays readable, it may use it later, reading the bitmap data in a lazy fashion. Most typically when the bitmap gets painted and that tends to crash your program fairly reliably with a "generic error".

You found another corner case, seems it just thinks there are no more properties. This is not otherwise that mysterious, you really did close the stream so there are no more properties it could possibly read. That it doesn't generate an exception for that is sloppy but not uncommon for GDI+.

Just get rid of the using statement, it doesn't do anything useful. If you fret about disposing the stream anyway then you must do so after you won't use the Bitmap object anymore.




回答2:


Because you created img2 out of scope of using statement so disposing stream does not affect it.

PropertyIdList is a method of Image not MemoryStream object.



来源:https://stackoverflow.com/questions/18215610/image-propertyitems-and-disposed-memorystream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!