c# - Parallel LINQ UnauthorizedAccessException when Aggregating results
问题描述
I am searching in parallel using LINQ
to find pattern matching files.
public class ParallelLinq
{
public IList<string> SearchFolders = new List<string>
{
@"C:\Windows" //can be multiple
};
protected virtual IEnumerable<string> GetFiles(string path, string[] searchPatterns, SearchOption searchOption = SearchOption.AllDirectories)
{
return searchPatterns.AsParallel()
.SelectMany(searchPattern =>
{
try
{
return Directory.EnumerateFiles(path, searchPattern, searchOption);
}
catch (Exception ex) //catch UnauthoizedException/IOExceptions
{
return Enumerable.Empty<string>();
}
});
}
public IEnumerable<string> Find(IList<string> patterns)
{
var testResultFiles = Enumerable.Empty<string>();
if (!SearchFolders.Any() || !patterns.Any())
{
return testResultFiles;
}
testResultFiles = SearchFolders.AsParallel().Aggregate(testResultFiles, (current, folder) => current.Union(GetFiles(folder, patterns.ToArray())));
return testResultFiles;
}
}
However when I try evaluate the values I am running into System.UnauthorizedAccessException: Access to the path 'C:\Windows\appcompat\Programs' is denied.
var plinq = new ParallelLinq();
var res = plinq.Find(new List<string> { "*.dll" });
Console.WriteLine("Linq Count: " + res.Count());
While these exceptions are expected, How can we catch them and continue ahead?
Full Exception:
Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.UnauthorizedAccessException: Access to the path 'C:\Windows\appcompat\Programs' is denied. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileSystemEnumerableIterator1.AddSearchableDirsToStack(SearchData localSearchData) at System.IO.FileSystemEnumerableIterator
1.MoveNext() at System.Linq.Parallel.SelectManyQueryOperator3.SelectManyQueryOperatorEnumerator
1.MoveNext(TOutput& currentElement, Pair2& currentKey) at System.Linq.Parallel.PipelineSpoolingTask
2.SpoolingWork() at System.Linq.Parallel.SpoolingTaskBase.Work() at System.Linq.Parallel.QueryTask.BaseWork(Object unused) at System.Linq.Parallel.QueryTask.<>c.<.cctor>b__10_0(Object o) at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.Execute() --- End of inner exception stack trace --- at System.Linq.Parallel.QueryTaskGroupState.QueryEnd(Boolean userInitiatedDispose) at System.Linq.Parallel.AsynchronousChannelMergeEnumerator1.MoveNextSlowPath() at System.Linq.Parallel.AsynchronousChannelMergeEnumerator
1.MoveNext()
at System.Linq.Parallel.QueryOpeningEnumerator1.MoveNext() at System.Linq.Enumerable.<UnionIterator>d__67
1.MoveNext() at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
解决方案
public class ParallelLinq
{
public IList<string> SearchFolders = new List<string>
{
@"C:\Windows" //can be multiple
};
private static string[] TryGetTopDirectories(string path)
{
try
{
return Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly);
}
catch
{
return new string[0];
}
}
private static IEnumerable<string> GetSubfolders(string path, SearchOption searchOption)
{
if (searchOption == SearchOption.TopDirectoryOnly)
{
return TryGetTopDirectories(path);
}
else
{
var topFolders = TryGetTopDirectories(path);
return topFolders.Concat(
topFolders.SelectMany(subFolder => GetSubfolders(subFolder, searchOption)));
}
}
protected virtual ParallelQuery<string> GetFiles(string path, string[] searchPatterns, SearchOption searchOption = SearchOption.AllDirectories)
{
return GetSubfolders(path, searchOption).AsParallel()
.SelectMany(subfolder =>
{
try
{
return searchPatterns.SelectMany(searchPattern => Directory.EnumerateFiles(subfolder, searchPattern)).ToArray();
}
catch (Exception ex) //catch UnauthoizedException/IOExceptions
{
return Enumerable.Empty<string>();
}
});
}
public IEnumerable<string> Find(IList<string> patterns)
{
var testResultFiles = Enumerable.Empty<string>();
if (!SearchFolders.Any() || !patterns.Any())
{
return testResultFiles;
}
testResultFiles = SearchFolders.AsParallel().Aggregate(testResultFiles, (current, folder) => current.Union(GetFiles(folder, patterns.ToArray())));
return testResultFiles;
}
}
推荐阅读
- java - 将具有多个 $expr 的 mongodb 查找写入 java
- ios - 在 Firebase iOS SDK 中更新实时数据库对象
- javascript - ReactJS + Redux props from mapStateToProps do not refresh on dispatching action
- python - 根据差异过滤数据帧有两个系列,一个通过字典映射
- vhdl - 在一行中分配一个 std_ulogic_vector 而不使用连接运算符 (&)
- excel - 我的条形码搜索不会在我的工作表中找到我的条形码。我的 vba 搜索代码无法正常工作
- php - 如何通过邮件在正文中发送图像?
- python - 导入带有常量的文件并抛出 AttributeError [Python 3]
- python - 在 groupby 循环中编号和创建数据帧
- elasticsearch - 如何关闭logstash计划并手动启动它?