本文介绍了Image PropertyItems和disposStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

输出:

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的内容直接支持并且解决方案是不处理它,或者我错了?

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?

在调试此问题的过程中我注意到了其他问题奇怪,如果我在中访问 PropertyIdList (或与图像 PropertyItems 相关的任何内容)在 MemoryStream 被处理后,使用块, PropertyItems 不会消失。

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

输出:

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

我查看了图像的来源class和 PropertyIdList 属性似乎没有保留 PropertyItems 数据的本地副本,那么为什么 PropertyItems 在这种情况下处理 MemoryStream 后保留?

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?

推荐答案

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

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.

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

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

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

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".

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

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+.

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

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.

这篇关于Image PropertyItems和disposStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-11 10:25