以下C#3.5代码在GetThumbnailImage中抛出异常:
Image img = null;
Image scaledImg = null;
byte[] imageData = File.ReadAllBytes("11001.jpg");
MemoryStream stream = new MemoryStream(imageData);
img = Image.FromStream(stream);
stream.Close();
stream.Dispose();
scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);
问题在于处理流。如果我删除Close()和Dispose()语句,一切正常。有谁知道为什么抛出这个异常?使用回调而不是null作为参数不会改变行为。
我不需要解决方案,我可以使用新的Bitmap(img,新的尺寸(宽度,高度)进行缩放。这可能更好,并且从一开始就使用了。
编辑:对不起,我忘了提到异常只发生在WindowsXP中。 Win7和Win8似乎正好处理上面的代码。
答案 0 :(得分:0)
我认为GetThumbnailImage
使用流来完成它的工作,因此需要它才能打开。你可以这样做:
Image img = null;
Image scaledImg = null;
byte[] imageData = File.ReadAllBytes("11001.jpg");
using(MemoryStream stream = new MemoryStream(imageData))
{
img = Image.FromStream(stream);
scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);
}
(using关闭并处理MemoryStream,但它也处理异常情况以避免内存泄漏)
答案 1 :(得分:0)
GetThumbnailImage
是一种原生方法,使用您在创建Image
时传递的相同流。只有.NET方法使用流中的实际数据(它是从流中创建图像时最后加载的)。
这是一个非常典型的漏洞抽象。您以为您有一个Image
对象已加载其数据,但数据仅加载在.NET部分中。任何直接与GDI +图像句柄一起工作的方法仍然需要流存在。
同一问题的另一个例子是尝试以不同的格式保存图像。当您尝试使用相同的格式进行保存时,.NET只会保存它在内存中的字节数据,这很简单。如果不相同,它将使用GDI +方法SaveImageToFile
,这又需要保留原始流。
如果你不介意让这个流存活,你可以在用你从该流产生的图像做的所有事情之后移动Dispose
:
using (var stream = new MemoryStream(imageData))
{
var img = Image.FromStream(stream);
var scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);
scaledImg.Save(...);
}
如果你介意的话,最简单的事情是:
var bmp = new Bitmap(Image.FromStream(stream));
Bitmap
构造函数将复制图像数据,您不再需要保留流。
答案 2 :(得分:0)
Image对象使用延迟评估。由于您已经关闭了流,当它实际上尝试读取图像以获取缩略图时,它不再存在。因此错误。