3

我正在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, 

所以看起来至少有一些PropertyItems是直接由内容支持的,MemoryStream解决方案是不处理它,还是我错了?

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

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数据的本地副本,那么为什么在这种情况下处置PropertyItems后保留?MemoryStream

4

2 回答 2

8

处理 MemoryStream 通常是一件相当无用的事情。它本身没有任何可支配资源,它只是内存并且已经由垃圾收集器管理。仅当您使用了 BeginRead/Write() 方法并且它们尚未完成时才重要,这是您从未做过的事情。

但是,它确实将 CanRead() 属性设置为 false。这对你从 MemoryStream 加载的 Bitmap 对象来说是相当致命的。

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

你发现了另一个极端案例,似乎它只是认为没有更多的属性。这并不是那么神秘,您确实关闭了流,因此它无法读取更多属性。它不会为此产生异常是草率的,但对于 GDI+ 来说并不少见。

只需摆脱using语句,它不会做任何有用的事情。如果您仍然担心要处理流,那么您必须在不再使用 Bitmap 对象之后这样做。

于 2013-08-13T17:59:59.437 回答
0

因为您创建img2using语句范围之外,所以处理流不会影响它。

PropertyIdList是 Image 不是MemoryStream对象的方法。

于 2013-08-13T17:56:40.713 回答