我正在使用LINQ
并行搜索以查找模式匹配文件。
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;
}
}
但是当我尝试评估我在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());
虽然预计会有这些例外情况,但我们如何抓住它们并继续前进?
完全例外:
未处理的异常:System.AggregateException:发生一个或多个错误。 ---> System.UnauthorizedAccessException:拒绝访问路径'C:\ Windows \ appcompat \ Programs'。在System.IO .__ Error.WinIOError(Int32 errorCode,String maybeFullPath) 在System.IO.FileSystemEnumerableIterator
1.AddSearchableDirsToStack(SearchData localSearchData) at System.IO.FileSystemEnumerableIterator
1.MoveNext()处于System.Linq.Parallel.SelectManyQueryOperator3.SelectManyQueryOperatorEnumerator
1.MoveNext(在System.Linq.Parallel.QueryTask的System.Linq.Parallel.SpoolingTaskBase.Work()中的TOutput&currentElement,Pair2& currentKey) at System.Linq.Parallel.PipelineSpoolingTask
2.SpoolingWork()。 System.Linq.Parallel.QueryTask中的BaseWork(Object unused)。<> c。 System__Threading.Tasks.Task.Execute()中System.Threading.Tasks.Task.InnerInvoke()的b__10_0(Object o)---内部异常堆栈跟踪结束---在System.Linq.Parallel.QueryTaskGroupState。 System.Linq.Parallel.AsynchronousChannelMergeEnumerator中的QueryEnd(Boolean userInitiatedDispose)1.MoveNextSlowPath() at System.Linq.Parallel.AsynchronousChannelMergeEnumerator
1.MoveNext() System.Linq.Enumerable.Count [TSource]上的System.Linq.Parallel.QueryOpeningEnumerator1.MoveNext() at System.Linq.Enumerable.<UnionIterator>d__67
1.MoveNext()处理(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;
}
}
似乎路径'C:\ Windows \ appcompat \ Programs'阻止程序创建文件。可以通过在文件夹本身中添加额外权限来解决此问题。