如何修复递归方法 C# 中的内存不足错误
How to fix out of memory error in a recursive method C#
我的问题是我有一个递归方法,该方法给出了它在所有子文件夹中输入的路径,并将文件名和一些信息存储在数据库中。
在我使用一个包含 31000 个文件和许多子文件夹的文件夹之前,它工作正常。我对该方法的参数是他正在工作的路径,父路径作为数据库 class 和数据库 class 来执行一些插入和选择。我的问题是使用 ref 关键字是否有助于解决内存问题?
抱歉,如果有关于此的文章。我什么也没找到。
public void ManageFiles(string path, Table Father, DataBaseHandlerClass DB)
{
try
{
log.Info("---------------------------Inicio Pasta " + path + "--------------------------");
DirectoryInfo d = new DirectoryInfo(path);
DirectoryInfo[] Dirs = d.GetDirectories();
int hashCode = path.GetHashCode();
IFB_FilePath FilePath = DB.InsertOrUpdatePath(hashCode, path, Father == null ? null : (int?)Father.ID);
foreach (var newPath in Dirs)
{
ManageFiles(newPath.FullName, FilePath, DB);
}
List<string> ext = DB.GetExtensionsToSearch();
FileInfo[] Files = d.GetFiles("*.*").Where(s => ext.Contains(s.Extension.ToLower())).ToArray();
var watch = System.Diagnostics.Stopwatch.StartNew();
foreach (FileInfo file in Files)
{
watch = System.Diagnostics.Stopwatch.StartNew();
FileTable Ficheiro = DB.InsertOrUpdateFile(file, FilePath);
if (Ficheiro.ID_Extension_Group == 1 && !Ficheiro.Metadata.Any())
{
CreateFileMetadata(DB, Ficheiro);
}
else
{
if (Ficheiro.ID_Extension_Group == 1 && Ficheiro.TakenDate == null)
{
UpdateTakenDate(DB, Ficheiro);
}
}
watch.Stop();
log.Info("Tempo em ms: " + watch.ElapsedMilliseconds + " Ficheiro " + file.Name);
}
log.Info("---------------------------Fim Pasta " + path + "--------------------------");
}
catch (Exception Ex)
{
log.Error(Ex);
}
}
虽然递归很漂亮而且有时需要的代码更少,但我建议您将其展开为循环。
C# 有递归深度,然后它超出了,运行时抛出错误。
但如果重写代码不是一种选择,您 can acquire bigger limit of recursion.
正如 this 网站所说,C# 中的嵌套可以像 14250 调用一样大。所以在你的情况下,调用函数 31000 次超过了这个限制。
我认为您应该首先将以下几行移到 ManageFiles
函数之外:
DirectoryInfo d = new DirectoryInfo(path);
DirectoryInfo[] Dirs = d.GetDirectories();
int hashCode = path.GetHashCode();
这是因为您在每次调用该函数时都会创建一个新的 DirectoryInfo
对象和目录集合。这是我要进行的第一个更改,因为它肯定会对内存产生影响。
我的问题是我有一个递归方法,该方法给出了它在所有子文件夹中输入的路径,并将文件名和一些信息存储在数据库中。 在我使用一个包含 31000 个文件和许多子文件夹的文件夹之前,它工作正常。我对该方法的参数是他正在工作的路径,父路径作为数据库 class 和数据库 class 来执行一些插入和选择。我的问题是使用 ref 关键字是否有助于解决内存问题?
抱歉,如果有关于此的文章。我什么也没找到。
public void ManageFiles(string path, Table Father, DataBaseHandlerClass DB)
{
try
{
log.Info("---------------------------Inicio Pasta " + path + "--------------------------");
DirectoryInfo d = new DirectoryInfo(path);
DirectoryInfo[] Dirs = d.GetDirectories();
int hashCode = path.GetHashCode();
IFB_FilePath FilePath = DB.InsertOrUpdatePath(hashCode, path, Father == null ? null : (int?)Father.ID);
foreach (var newPath in Dirs)
{
ManageFiles(newPath.FullName, FilePath, DB);
}
List<string> ext = DB.GetExtensionsToSearch();
FileInfo[] Files = d.GetFiles("*.*").Where(s => ext.Contains(s.Extension.ToLower())).ToArray();
var watch = System.Diagnostics.Stopwatch.StartNew();
foreach (FileInfo file in Files)
{
watch = System.Diagnostics.Stopwatch.StartNew();
FileTable Ficheiro = DB.InsertOrUpdateFile(file, FilePath);
if (Ficheiro.ID_Extension_Group == 1 && !Ficheiro.Metadata.Any())
{
CreateFileMetadata(DB, Ficheiro);
}
else
{
if (Ficheiro.ID_Extension_Group == 1 && Ficheiro.TakenDate == null)
{
UpdateTakenDate(DB, Ficheiro);
}
}
watch.Stop();
log.Info("Tempo em ms: " + watch.ElapsedMilliseconds + " Ficheiro " + file.Name);
}
log.Info("---------------------------Fim Pasta " + path + "--------------------------");
}
catch (Exception Ex)
{
log.Error(Ex);
}
}
虽然递归很漂亮而且有时需要的代码更少,但我建议您将其展开为循环。 C# 有递归深度,然后它超出了,运行时抛出错误。
但如果重写代码不是一种选择,您 can acquire bigger limit of recursion.
正如 this 网站所说,C# 中的嵌套可以像 14250 调用一样大。所以在你的情况下,调用函数 31000 次超过了这个限制。
我认为您应该首先将以下几行移到 ManageFiles
函数之外:
DirectoryInfo d = new DirectoryInfo(path);
DirectoryInfo[] Dirs = d.GetDirectories();
int hashCode = path.GetHashCode();
这是因为您在每次调用该函数时都会创建一个新的 DirectoryInfo
对象和目录集合。这是我要进行的第一个更改,因为它肯定会对内存产生影响。