【发布时间】:2015-06-22 03:25:50
【问题描述】:
目前我有一个大约 170,000 个 jpg 文件名的 .txt 文件,我将它们全部读入一个列表 (fileNames)。
我想搜索一个文件夹(这个文件夹有子文件夹)来检查 fileNames 中的每个文件是否存在于这个文件夹中,如果存在,请将其复制到一个新文件夹中。
我做了一个粗略的估计,但每次搜索和复制 fileNames 中的每个文件名大约需要 0.5 秒。所以 170,000 秒大约是 48 小时,所以除以 2 后,我的应用需要大约 24 小时才能使用 1 个线程搜索每个文件名!显然这太长了,所以我想缩小范围并加快进程。使用多线程执行此操作的最佳方法是什么?
目前我正在考虑创建 20 个单独的线程并将我的列表(文件名)拆分为 20 个不同的列表并同时搜索文件。例如,我将有 20 个不同的线程同时执行以下操作:
foreach (string str in fileNames)
{
foreach (var file in Directory.GetFiles(folderToCheckForFileName, str, SearchOption.AllDirectories))
{
string combinedPath = Path.Combine(newTargetDirectory, Path.GetFileName(file));
if (!File.Exists(combinedPath))
{
File.Copy(file, combinedPath);
}
}
}
更新后在下方显示我的解决方案:
string[] folderToCheckForFileNames = Directory.GetFiles("C:\\Users\\Alex\\Desktop\\ok", "*.jpg", SearchOption.AllDirectories);
foreach(string str in fileNames)
{
Parallel.ForEach(folderToCheckForFileNames, currentFile =>
{
string filename = Path.GetFileName(currentFile);
if (str == filename)
{
string combinedPath = Path.Combine(targetDir, filename);
if (!File.Exists(combinedPath))
{
File.Copy(currentFile, combinedPath);
Console.WriteLine("FOUND A MATCH AND COPIED" + currentFile);
}
}
}
);
}
感谢大家的贡献!非常感谢!
【问题讨论】:
-
如果我没看错的话,为什么不将所有文件名读入内存,比如 HashSet,然后用它来搜索文件。至于使用多线程加速磁盘 IO,仅此而已。一旦磁盘 IO 被最大化,你有多少线程都没有关系。
-
不仅仅是磁盘 IO,它还严重依赖于可用于处理线程逻辑的处理核心的数量,因此最终是一个糟糕的解决方案
-
您尝试过使用 TPL foreach 吗? msdn.microsoft.com/en-us/library/dd460720(v=vs.110).aspx
-
所以你们是说实际上将所有实际的 .jpg 文件从 folderToCheckForFileName 读入内存并进行搜索?而不是检查我机器上的实际文件夹?
-
不要读取文件,只读取文件名列表
标签: c# multithreading file-search