Image PropertyItems和已释放的MemoryStream
本文关键字:MemoryStream 释放 PropertyItems Image | 更新日期: 2023-09-27 18:27:27
我正在使用MemoryStream
从byte[]
加载Image
,并通过检查图像的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,
因此,似乎至少有一些PropertyItems
是由MemoryStream
的内容直接支持的,解决方案是不处理它,还是我错了?
在调试这个问题的过程中,尽管我注意到了一些奇怪的事情,但如果我访问using
块内的PropertyIdList
(或与图像PropertyItems
相关的任何东西),则在MemoryStream
被处理后,PropertyItems
不会消失。
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
数据的本地副本,那么在这种情况下,为什么在处理MemoryStream
之后保留PropertyItems
呢?
处理MemoryStream通常是一件非常无用的事情。它本身没有任何可丢弃的资源,它只是内存,已经由垃圾收集器管理。只有当你已经使用了BeginRead/Write()方法,但它们还没有完成,这才是重要的,这是你从未做过的
但是,它确实将CanRead()属性设置为false。这对从MemoryStream加载的位图对象来说是非常致命的。
当您继续使用位图时,接下来会发生什么是不可预测的。GDI+要求流保持可读性,它可以在以后使用它,以惰性的方式读取位图数据。最常见的情况是,当位图被绘制时,这往往会导致程序相当可靠地崩溃,并出现"一般错误"。
你发现了另一个角落的案例,似乎它只是认为没有更多的财产。这并不是那么神秘,你确实关闭了流,所以它不可能读取更多的属性。它没有为此生成异常是草率的,但对于GDI+来说并不罕见。
只要使用语句去掉,它就没有任何用处。如果您无论如何都在为处理流而烦恼,那么在不再使用位图对象之后,必须这样做。
因为您在using
语句的范围之外创建了img2
,所以处理流不会影响它。
CCD_ 21是图像而非CCD_ 22对象的方法。