通过网络优化Dictionary.EnumerateFiles

时间:2014-11-14 16:29:34

标签: c# .net multithreading optimization

我目前有一个扫描网络共享的程序。为此,它首先枚举共享上的所有文件和目录。这是一个非常缓慢的过程。我目前使用以下代码,取自本网站2011年的答案。

static class SafeWalk
    {
        public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOpt)
        {
            try
            {
                var dirFiles = Enumerable.Empty<string>();
                if (searchOpt == SearchOption.AllDirectories)
                {
                    dirFiles = Directory.EnumerateDirectories(path)
                                        .SelectMany(x => EnumerateFiles(x, searchPattern, searchOpt));
                }
                return dirFiles.Concat(Directory.EnumerateFiles(path, searchPattern));
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine(ex.Message);
                return Enumerable.Empty<string>();
            }
        }
    }

问题在于程序中的其他所有内容都是多线程的,并针对速度进行了优化。这是唯一一个严重阻碍我的领域。枚举网络共享中的文件可能需要几分钟。这是在Intranet上,我的机器和服务器之间有千兆位或更大的连接。

当我在运行时临时将网络路径映射到驱动器时​​,我确实加快了速度。有什么办法可以让它变得更快吗?查看资源监视器,它几乎不使用任何CPU,内存或网络带宽。

3 个答案:

答案 0 :(得分:2)

考虑使用PInvoke使用选项FIND_FIRST_EX_LARGE_FETCH来呼叫FindFirstFileExAccording to Raymond Chen this flag is made for your situation

答案 1 :(得分:0)

您是否经常使用相同的搜索参数搜索相同的路径?你使用缓存结果还可以吗?如果是这样,我建议添加一个缓存机制。我们遇到过类似的事情,虽然我们并没有将它暴露得如此通用和细化,我只是缓存了结果。或者,如果您对此不满意,调用者的逻辑是否可能不保存结果并且循环多次调用?

答案 2 :(得分:-2)

Fast Directory Enumerator 是适合你的。

为什么它更快?

Directory.GetFiles和DirectoryInfo.GetFiles或Directory.EnumerateFile()有许多缺点。最重要的是它们丢弃信息并且不能有效地允许您同时检索有关多个文件的信息。

在内部,Directory.GetFiles实现为Win32 FindFirstFile / FindNextFile函数的包装器。这些函数都返回有关枚举的每个文件的信息,GetFiles()方法在返回文件名时抛出这些文件。他们还使用单个网络消息检索有关多个文件的信息。

FastDirectoryEnumerator保留此信息并将其返回到FileData类中。这大大减少了完成相同任务所需的网络往返次数。