问题描述
我正在使用 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!