我试图遍历所有文件和文件夹,并对具有特定扩展名的所有文件执行操作.这种方法工作正常,但我想让它多线程,因为当完成数以万计的文件时,它真的很慢,我会使用多线程进行成像会加快速度.在这种情况下,我只是不确定如何使用线程.
doStuff 从文件中读取属性(修改日期等,并将它们插入到sqlite数据库中.我在调用扫描方法之前启动一个事务,以便尽可能地优化它.
提供有关如何执行此操作的理论的答案与完整的代码答案一样好.
private static string[] validTypes = { ".x", ".y", ".z", ".etc" };
public static void scan(string rootDirectory)
{
try
{
foreach (string dir in Directory.GetDirectories(rootDirectory))
{
if (dir.ToLower().IndexOf("$recycle.bin") == -1)
scan(dir);
}
foreach (string file in Directory.GetFiles(rootDirectory))
{
if (!((IList<string>)validTypes).Contains(Path.GetExtension(file)))
{
continue;
}
doStuff(file);
}
}
catch (Exception)
{
}
}
Run Code Online (Sandbox Code Playgroud)
假设doStuff是线程安全的,而且你不需要等待整个扫描完成,你可以打电话都doStuff和scan上线程池,如下所示:
string path = file;
ThreadPool.QueueUserWorkItem(delegate { doStuff(path); });
Run Code Online (Sandbox Code Playgroud)
您需要创建一个单独的局部变量,因为匿名方法file本身会捕获变量,并且会在整个循环中看到对它的更改.(换句话说,如果ThreadPool仅在循环继续到下一个文件后执行任务,它将处理错误的文件)
但是,阅读你的评论,这里的主要问题是磁盘IO,所以我怀疑多线程不会有多大帮助.
请注意,Directory.GetFiles对于具有大量文件的目录,执行速度会很慢.(因为它需要分配一个数组来保存文件名)
如果您正在使用.Net 4.0,您可以通过调用该EnumerateFiles方法来加快速度,它使用迭代器返回一个IEnumerable<string>在运行循环时枚举目录的方法.
您还scan可以通过传递SearchOption参数来避免使用任一方法进行递归调用,如下所示:
foreach (string file in Directory.EnumerateFiles(rootDirectory, "*", SearchOption.AllDirectories))
Run Code Online (Sandbox Code Playgroud)
这将递归扫描所有子目录,因此您只需要一个foreach循环.
请注意,这会加剧性能问题GetFiles,因此您可能希望避免使用此preNet.Net 4.0.