我做了一个非常简单的程序,可以在外部HDD上找到图片,并将它们放入文件夹中。这听起来很简单,但出于某种原因,我在这样做的时候得到了“Out of Memory”异常。
我已经在64位Win10上测试了4 GB的内存,64位的Win10和32 GB的内存。然而,我仍然在两个系统上都获得了“Out of Memory”异常。
我的平台目标是x64。
这是发生错误的代码:
string[] filePaths = Directory.GetFiles(Stien, "*.*", SearchOption.AllDirectories);
foreach (string file in filePaths)
{
string[] TempValue1 = file.Split(new[] { @"\" }, StringSplitOptions.None);
string FileName = TempValue1[TempValue1.Length - 1];
if (FileName.Contains(SøgeTerm)) //Checks if the name contains the search-term.
{
if (!SortDate) //If the program was told not to sort by date.
{
try
{
File.Copy(file, destination + @"\" + FileName, true);
Console.WriteLine(FileName + " => " + destination + @"\" + FileName);
}
catch (Exception e)
{
Console.WriteLine("Fejl: " + e.ToString());
}
}
else
{
Image Billede = Bitmap.FromFile(file);
string date;
try
{
PropertyItem propItem = Billede.GetPropertyItem(36867);
date = r.Replace(Encoding.UTF8.GetString(propItem.Value), "-", 2);
date = date.Split(new[] { ' ' }, StringSplitOptions.None)[0];
propItem = null;
}
catch
{
date = "UKENDT";
}
//
if (!Directory.Exists(destination + @"\" + date))
{
Directory.CreateDirectory(destination + @"\" + date);
Console.WriteLine(destination + @"\" + date);
}
File.Copy(file, destination + @"\" + date + @"\" + FileName, true); //Copies the file, and places it into the fitting folder.
Console.WriteLine(FileName + " => " + destination + @"\" + "" + date + @"\" + FileName);
date = null; //I thought this might helped clearing some memory.
Billede = null;
}
}
}
所以我的问题:导致异常的原因是什么,我该如何解决?
如其他答案中所述,您可以使用using statement以正确的方式在对象上调用Dispose
方法。
using (Image Billede = Bitmap.FromFile(file)){
...
}
但是,对于您的代码,您可能需要检查图像格式,因为如果(来自MSDN),Image.FromFile
函数将抛出OutOfMemoryException
:
该文件没有有效的图像格式。
-要么-
GDI +不支持文件的像素格式。
看看this
您不仅要复制文件,还要将位图加载到内存中,这就是它最终耗尽内存的原因。
Image Billede = Bitmap.FromFile(file);
仅将值设置为null
是不够的,您需要处理该对象。
所以,而不是
Billede = null;
做
Billede.Dispose();
编辑:这样你就可以在代码中进行最少量的更改。但是,使用USING
语句是一种更好的做法(其他答案举例说明)。
PS - 有一些方法可以加载图像元数据而无需将整个图像加载到内存中。
PPS - 阅读此内容以获取加载日期信息的方法,而无需将整个图像加载到内存中。它还应该使你的代码运行得更快:How can I find out when a picture was actually taken in C# running on Vista?
Image
和Bitmap
实施IDisposable
。因此,您必须将其用法包装在using
语句中以释放其资源。
using (Image Billede = Bitmap.FromFile(file)){
...
}
虽然图像最终会被最终确定并发布,但在此之前你可能会耗尽内存。