2014-11-14 74 views
4

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

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,内存或网络带宽。

+1

而不是创建一个递归方法,对于['Directory.EnumerateFiles'](http://msdn.microsoft.com/en-us/library/dd383571%28v)使用适当的重载不会更容易= vs.110%29.aspx)? – 2014-11-14 16:33:37

+0

如果您无权访问文件/目录,Directory.EnumerateFiles将引发错误。如果这样做,它只会返回迄今为止发现的内容,可能是70GB中的3MB。 :-( – 2014-11-14 16:37:21

+0

然后我猜你唯一的选择就是下面链接的快速目录枚举器。在C#中反复捕获异常和递归方法将比直接枚举慢,但... – 2014-11-14 16:43:14

回答

-1

Fast Directory Enumerator 是你的事情。

为什么它更快?

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

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

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

+2

不,该项目会在.NET 4.0中添加EnumerateFiles/Directory()方法。这解决了完全相同的问题。 OP已经在使用它。 – 2014-11-14 17:01:03

+2

试图使用这个库:在我的当前解决方案的初始测试中,它大约慢了5倍。 – 2014-11-14 17:09:05

+0

上次我查看使用Reflector时,FindFirstFile中的信息没有被丢弃。 – usr 2014-11-14 17:57:22

2

考虑使用PInvoke以FIND_FIRST_EX_LARGE_FETCH的选项拨打FindFirstFileExAccording to Raymond Chen this flag is made for your situation

+0

不幸的是,该值对Windows 7无效。 – 2014-11-17 14:59:31

+0

@Red_Shadow在这种情况下,我建议您编写一个在远程计算机上运行的小应用程序,并公开一个API来枚举目录。然后,您可以使用快速本地枚举并以非繁琐的方式高效地在网络上传输结果。 – usr 2014-11-17 15:04:06

+0

实际上,重读msdn,我认为它支持Windows 7及以上版本,它只是措辞笨拙。另外,我无法在远程机器上执行任何代码。该工具应该安装在扫描仪上,并且能够扫描网络上的任何其他机器。 – 2014-11-17 15:06:02

0

您是否正在搜索具有相同搜索参数的相同路径,而这个路径通常在大量的情况下?你确定使用缓存结果吗?如果是这样,我建议添加一个缓存机制。我们遇到了类似的情况,虽然我们并没有将它暴露得如此普遍和细致,而我只是缓存了结果。或者,如果您对此不满意,是否有可能调用者的逻辑没有保存结果,并且正在多次调用此循环?