【发布时间】:2026-01-25 04:50:01
【问题描述】:
我正在尝试加速由一个路径递归给出的所有文件夹中所有文件的总和计算。
假设我选择“E:\”作为文件夹。 我现在将以毫秒为单位通过“SafeFileEnumerator”将条目递归文件列表放入 IEnumerable(就像一个魅力)
现在我想从这个 Enumerable 中的所有文件中收集所有字节的总和。 现在我通过 foreach 循环它们并获取 FileInfo(oFileInfo.FullName).Length; - 对于每个文件。
这是有效的,但速度很慢 - 大约需要 30 秒。如果我通过 Windows 右键单击查找空间消耗 - Windows 资源管理器中所有选定文件夹的属性,我会在大约 6 秒内得到它们(在 ssd 上的 26 GB 数据中大约有 1600 个文件)
所以我的第一个想法是通过使用线程来加速收集,但我在这里没有得到任何加速..
没有线程的代码如下:
public static long fetchFolderSize(string Folder, CancellationTokenSource oCancelToken)
{
long FolderSize = 0;
IEnumerable<FileSystemInfo> aFiles = new SafeFileEnumerator(Folder, "*", SearchOption.AllDirectories);
foreach (FileSystemInfo oFileInfo in aFiles)
{
// check if we will cancel now
if (oCancelToken.Token.IsCancellationRequested)
{
throw new OperationCanceledException();
}
try
{
FolderSize += new FileInfo(oFileInfo.FullName).Length;
}
catch (Exception oException)
{
Debug.WriteLine(oException.Message);
}
}
return FolderSize;
}
多线程代码如下:
public static long fetchFolderSize(string Folder, CancellationTokenSource oCancelToken)
{
long FolderSize = 0;
int iCountTasks = 0;
IEnumerable<FileSystemInfo> aFiles = new SafeFileEnumerator(Folder, "*", SearchOption.AllDirectories);
foreach (FileSystemInfo oFileInfo in aFiles)
{
// check if we will cancel now
if (oCancelToken.Token.IsCancellationRequested)
{
throw new OperationCanceledException();
}
if (iCountTasks < 10)
{
iCountTasks++;
Thread oThread = new Thread(delegate()
{
try
{
FolderSize += new FileInfo(oFileInfo.FullName).Length;
}
catch (Exception oException)
{
Debug.WriteLine(oException.Message);
}
iCountTasks--;
});
oThread.Start();
continue;
}
try
{
FolderSize += new FileInfo(oFileInfo.FullName).Length;
}
catch (Exception oException)
{
Debug.WriteLine(oException.Message);
}
}
return FolderSize;
}
有人可以给我一个建议,我可以如何加快文件夹大小的计算过程吗?
问候
编辑 1(Parallel.Foreach 建议 - 请参阅 cmets)
public static long fetchFolderSize(string Folder, CancellationTokenSource oCancelToken)
{
long FolderSize = 0;
ParallelOptions oParallelOptions = new ParallelOptions();
oParallelOptions.CancellationToken = oCancelToken.Token;
oParallelOptions.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
IEnumerable<FileSystemInfo> aFiles = new SafeFileEnumerator(Folder, "*", SearchOption.AllDirectories).ToArray();
Parallel.ForEach(aFiles, oParallelOptions, oFileInfo =>
{
try
{
FolderSize += new FileInfo(oFileInfo.FullName).Length;
}
catch (Exception oException)
{
Debug.WriteLine(oException.Message);
}
});
return FolderSize;
}
【问题讨论】:
标签: c# wpf multithreading io filesize