2017-10-21 106 views
2

我碰到了一些不錯的職位來獲得使用下一個代碼文件和/或文件夾的總數的EnumeratFiles在PLINQ查詢C#例外:如何處理上EnumeratFolders

DirectoryInfo dirInfo = new DirectoryInfo(myBaseDirectory + @"\"); 
      var count = await Task.FromResult(dirInfo.EnumerateDirectories() 
        .AsParallel() 
        .SelectMany(di => di.EnumerateFiles("*.*", SearchOption.AllDirectories)) 
        .Count() + dirInfo.EnumerateFiles("*.*", SearchOption.TopDirectoryOnly).Count()); 

這個偉大的工程。直到我試圖訪問一個NTFS格式的驅動器。然後在EnumerateFiles函數上引發一個異常。這是卷信息文件夾上的UnauthorizedAccessException。

現在我的問題是,我怎樣才能以這樣的方式重寫這段代碼,當拋出異常時,代碼會保持「循環」。換句話說,它只是跳過引發異常的文件或文件夾。

我試圖抓住整個代碼無法正常工作。據我瞭解,現在我應該在selectMany部分中加入try-catch。例如:

.SelectMany(di => { try { di.EnumerateFiles("*.*", SearchOption.AllDirectories); } catch{ }}) 

但是然後代碼不能編譯。有什麼建議麼?

+0

什麼是編譯器錯誤?除了非常緩慢,它應該工作。沒有規則可以阻止lambda函數體內的try ... catch。 – dlatikay

+0

Try ... catch結構不會返回任何內容,因此SelectMany無效。嘗試在'di.EnumerateFiles'之前放置'return',並在catch中返回一個空的枚舉(你也可以明確地捕獲'UnauthorizedAccessException',以便仍然拋出其他意外的錯誤) –

+0

您確定並行實際上會提高性能嗎?據猜測,我敢說這會增加磁盤抖動,並且實際上會降低性能。您可以同時發出多個IO請求,但是您仍然只有一個硬盤驅動器,其運行速度比甚至單個同步線程慢很多。 – spender

回答

0

當存在像try..catch這樣的塊語句(more here)時,不能使用短lambda語法(表示其唯一語句的表達式值作爲返回值)。
在你的情況,你需要使用return聲明,表示其表達lambda函數的結果:

SelectMany(di => { 
    try 
    { 
     return di.EnumerateFiles("*.*", SearchOption.AllDirectories); 
    } 
    catch 
    { 
     /* just skip */ 
     return new FileInfo[] { }; 
    } 
}) 
+0

這樣做。謝謝。它與Me.name相同。目前沒有性能問題 – Stephan