2014-11-14 72 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

您是否正在搜索具有相同搜索參數的相同路徑,而這個路徑通常在大量的情況下?你確定使用緩存結果嗎?如果是這樣,我建議添加一個緩存機制。我們遇到了類似的情況,雖然我們並沒有將它暴露得如此普遍和細緻,而我只是緩存了結果。或者,如果您對此不滿意,是否有可能調用者的邏輯沒有保存結果,並且正在多次調用此循環?