C# 处理大量图像时出现内存不足异常
Im使用以下代码根据EXIF数据修复图像的方向C# 处理大量图像时出现内存不足异常,c#,.net,bitmap,out-of-memory,gdi+,C#,.net,Bitmap,Out Of Memory,Gdi+,Im使用以下代码根据EXIF数据修复图像的方向 Image FixImageOrientation(Image srce) { const int ExifOrientationId = 0x112; // Read orientation tag if (!srce.PropertyIdList.Contains(ExifOrientationId)) return srce; v
Image FixImageOrientation(Image srce)
{
const int ExifOrientationId = 0x112;
// Read orientation tag
if (!srce.PropertyIdList.Contains(ExifOrientationId)) return srce;
var prop = srce.GetPropertyItem(ExifOrientationId);
var orient = BitConverter.ToInt16(prop.Value, 0);
// Force value to 1
prop.Value = BitConverter.GetBytes((short)1);
srce.SetPropertyItem(prop);
// MessageBox.Show(orient.ToString());
// Rotate/flip image according to <orient>
switch (orient)
{
case 1:
srce.RotateFlip(RotateFlipType.RotateNoneFlipNone);
return srce;
case 2:
srce.RotateFlip(RotateFlipType.RotateNoneFlipX);
return srce;
case 3:
srce.RotateFlip(RotateFlipType.Rotate180FlipNone);
return srce;
case 4:
srce.RotateFlip(RotateFlipType.Rotate180FlipX);
return srce;
case 5:
srce.RotateFlip(RotateFlipType.Rotate90FlipX);
return srce;
case 6:
srce.RotateFlip(RotateFlipType.Rotate90FlipNone);
return srce;
case 7:
srce.RotateFlip(RotateFlipType.Rotate270FlipX);
return srce;
case 8:
srce.RotateFlip(RotateFlipType.Rotate270FlipNone);
return srce;
default:
srce.RotateFlip(RotateFlipType.RotateNoneFlipNone);
return srce;
}
}
为什么我会得到这个。。我想我会在循环结束时处理此图像。在代码中创建两个位图,但只处理一个。 更改您的代码:
using(var source = Bitmap.FromFile(filepath)) {
using(var image = new Bitmap(FixImageOrientation(source))) {
// ... do long processing
}
}
这将解决您的问题。在代码中创建两个位图,但只处理一个。 更改您的代码:
using(var source = Bitmap.FromFile(filepath)) {
using(var image = new Bitmap(FixImageOrientation(source))) {
// ... do long processing
}
}
这应该可以解决您的问题。您可以在这个答案中找到,调用dispose并不一定会释放内存。这是垃圾收集器的任务。我假设,您正在相当快地将图像加载到内存中。问题是,垃圾收集只是偶尔进行。如果您通过创建新对象来使用大量内存,垃圾收集可能会因为再次释放内存而变慢 您可以尝试使用GC.Collect()从循环中直接调用它。 如果这还不够,还可以尝试blocking参数,它将暂停线程,直到GC运行完成 作为一种不同的方法,您可以将项目设置为x64编译,这将使您的程序能够访问超过1GB的内存。但有了这个解决方案,你只会把问题推得更远
Thomas正如您在本回答中所发现的,调用dispose并不一定会释放内存。这是垃圾收集器的任务。我假设,您正在相当快地将图像加载到内存中。问题是,垃圾收集只是偶尔进行。如果您通过创建新对象来使用大量内存,垃圾收集可能会因为再次释放内存而变慢 您可以尝试使用GC.Collect()从循环中直接调用它。 如果这还不够,还可以尝试blocking参数,它将暂停线程,直到GC运行完成 作为一种不同的方法,您可以将项目设置为x64编译,这将使您的程序能够访问超过1GB的内存。但有了这个解决方案,你只会把问题推得更远
托马斯在记录的千次循环中出现内存不足异常,一种可能的解决方案:
千条记录的FOR循环内存不足异常,一种可能的解决方案:
您正在创建两个图像,并且仅处理一个
位图。FromFile(filepath)
和新位图(
)。这样,在运行程序时打开windows任务管理。如果您看到内存快速增加,则表明某个地方内存泄漏,您正在创建两个图像,并且仅处理一个位图.FromFile(filepath)
和新建位图(
.Ghetto方式,在运行程序时打开windows任务管理。如果您看到内存快速增长,则表示内存在某处泄漏,谢谢..因为图像是全局对象..我想我可以简单地使用使用(var source=Bitmap.FromFile(filepath)){位图图像=新建位图(fixamageorientation(source));}
并使用image.dispose()关闭image
。这样行吗?@techno抱歉,我不明白你的意思。你必须处理两个位图。我的意思是..我在代码中分配image
对象。如果我使用use
语句处理image
,我就不能这样做,所以我只是使用(var source=Bitmap.FromFile(filepath))使用{
并从源代码创建图像
并手动处理图像
对象…而不是使用
语句使用第二个对象。我无法自..无法为使用
语句创建的对象赋值。为什么需要重新分配图像
对象?谢谢..因为image是一个全局对象。我想我可以简单地使用使用(var source=Bitmap.FromFile(filepath)){Bitmap image=new Bitmap(fixmageorientation(source));}
和dispose offimage
使用image.dispose()
。这样行吗?@techno抱歉,我不明白你的意思。你必须处理两个位图。我的意思是..我在代码中分配image
对象。如果我使用use
语句处理image
,我就不能这样做,所以我只是使用(var source=Bitmap.FromFile(filepath))使用{
并从源代码创建图像
并手动处理图像
对象…而不是使用
语句使用第二个对象。我无法从..开始为使用
语句创建的对象赋值。为什么需要重新赋值图像
?
using(var source = Bitmap.FromFile(filepath)) {
using(var image = new Bitmap(FixImageOrientation(source))) {
// ... do long processing
}
}