2017-10-21 86 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