代码之家  ›  专栏  ›  技术社区  ›  Alec Gorge

C语言中的多线程目录循环#

  •  4
  • Alec Gorge  · 技术社区  · 14 年前

    doStuff 从文件中读取属性(修改日期等),并将其插入sqlite数据库。我在调用scan方法之前启动一个事务,以便尽可能优化它。

    提供如何做的理论的答案和完整的工作代码答案一样好。

        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)
            {
            }
        }
    
    5 回复  |  直到 14 年前
        1
  •  5
  •   SLaks    14 年前

    假设 doStuff 是线程安全的,并且您不需要等待整个扫描完成,您可以同时调用这两者 多斯凝灰岩 scan 在线程池上,如下所示:

    string path = file;
    ThreadPool.QueueUserWorkItem(delegate { doStuff(path); });
    

    您需要创建一个单独的局部变量,因为匿名方法必须捕获 file 变量本身,并在整个循环中看到对它的更改(换句话说,如果线程池只是在循环继续到下一个文件之后才执行任务,它将处理错误的文件)

    然而,阅读您的评论,这里的主要问题是磁盘IO,所以我怀疑多线程将不会有多大帮助。

    请注意 Directory.GetFiles
    EnumerateFiles method IEnumerable<string> 它在运行循环时枚举目录。
    也可以避免递归 扫描 通过传递 SearchOption

    foreach (string file in Directory.EnumerateFiles(rootDirectory, "*", SearchOption.AllDirectories))
    

    这将递归地扫描所有子目录,所以您只需要一个 foreach 循环。
    GetFiles ,因此您可能希望避免使用.Net 4.0之前的版本。

        2
  •  2
  •   Dan Tao    14 年前

    在IO操作上使用多线程通常是一个错误的调用*。您可能有多个CPU或一个CPU有多个核心;但总的来说, . 这类事情通常需要序列化。

    也就是说,在与UI线程分离的线程上执行这种工作是一种很好的做法。这样,当你的应用程序正在进行繁重的工作时,用户界面仍能保持响应。

    *我假设你 scan doStuff 方法实际上是在硬盘上读取和/或写入数据。如果不是这样的话,那么并行化这段代码可能还是有意义的。

        3
  •  1
  •   Hans Olsson    14 年前

    doStuff scan 你知道吗?除非它们是非常CPU密集型的,否则我会认为磁盘访问将是瓶颈,如果有什么使它成为多线程可能会更慢。

        4
  •  1
  •   Winston Smith    14 年前

    validTypes IList<string> 因为数组实现 IEnumerable<T>

    作为一个 HashSet ,提供O(1)查找,而不是O(n)查找 Contains . 也就是说,在这种情况下,这可能不会影响性能,因为正如其他答案所指出的,应用程序是IO绑定的。

        5
  •  0
  •   Alec Gorge    14 年前

            foreach (string file in Directory.EnumerateFiles(rootDirectory, "*", SearchOption.AllDirectories))
            {
                if (!((IList<string>)validTypes).Contains(Path.GetExtension(file)))
                {
                    continue;
                }
                string path = file;
                ThreadPool.QueueUserWorkItem(delegate { doStuff(path); });
            }
    

    与之前的几个小时相比,这只花了大约2分钟。我想大部分的延迟是在数据库中,而不是在文件IO中。

    非常感谢大家!