Image PropertyItems和disposStream

时间:2013-08-13 17:34:46

标签: c# image dispose using

我正在使用Imagebyte[]加载MemoryStream,并通过检查ProperyItems获取有关该图像的信息。在这样做的过程中,我注意到一些奇怪的行为,其中一些图像的PropertyItems正在消失。经过多次调试后,我终于发现这是由MemoryStream被处理引起的。

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");

输出:

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, 

所以似乎至少有一些PropertyItemsMemoryStream的内容直接支持,解决方案是不处理它,或者我错了?

在调试此问题的过程中虽然我注意到其他奇怪的事情,但如果我在PropertyIdList块内访问PropertyItems(或与图像using相关的任何内容),处置PropertyItems后,MemoryStream不会消失。

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");

输出:

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

我查看了Image类的源代码,PropertyIdList属性似乎没有保留PropertyItems数据的本地副本,为什么{{1}在这种情况下处置PropertyItems后保留?

2 个答案:

答案 0 :(得分:7)

处理MemoryStream通常是一件相当无用的事情。它本身没有任何可支配资源,它只是内存,而且已经由垃圾收集器管理。只有你使用了BeginRead / Write()方法并且它们还没有完成,这是你永远不会做的事情。

但它确实将CanRead()属性设置为false。这对你从MemoryStream加载的Bitmap对象非常致命。

接下来,当你继续使用Bitmap时,会发生什么是相当不可预测的。 GDI +要求流保持可读性,它可以使用它以后,以懒惰的方式读取位图数据。最典型的情况是,当位图被绘制时,会因“一般错误”而相当可靠地使程序崩溃。

你找到了另一个角落案例,似乎只是认为没有更多的属性。这不是那么神秘,你真的关闭了流,所以它没有更多可能读取的属性。对于GDI +而言,它不会产生异常,但这并不罕见。

只是摆脱使用语句,它没有做任何有用的事情。如果你担心无论如何处理流,那么必须在你不再使用Bitmap对象之后这样做。

答案 1 :(得分:0)

因为您在img2语句的范围之外创建了using,所以处理流不会影响它。

PropertyIdList是Image not MemoryStream object的方法。