Мне нужно найти подстроку в более чем 10k файлах и вернуть первое совпадение.Для этого я написал этот метод, используя класс Parallel
:
public class FileSearchResult
{
public long Id { get; }
public string FilePath { get; }
public IList<SearchMatch> Matches { get; }
public FileSearchResult(long id, string filePath)
{
Id = id;
FilePath = filePath;
Matches = new List<SearchMatch>();
}
}
public class SearchMatch
{
public int Index { get; set; }
public int Length { get; set; }
}
public FileSearchResult[] SearchInFiles(string query, string[] filePathList)
{
if (string.IsNullOrWhiteSpace(query) || filePathList == null || filePathList.Length == 0)
{
return Array.Empty<FileSearchResult>();
}
Regex regex = new Regex(query, RegexOptions.IgnoreCase | RegexOptions.Multiline);
ConcurrentBag<FileSearchResult> matchesList = new ConcurrentBag<FileSearchResult>();
Parallel
.ForEach
(
filePathList,
(file, state, ix) =>
{
if (state.ShouldExitCurrentIteration)
{
return;
}
string fileContent = File.ReadAllText(file);
var results = regex.Matches(fileContent);
if (results.Count == 0)
{
return;
}
state.Break();
//if(state.LowestBreakIteration.HasValue)
//{
// Interlocked.Exchange(ref lowestBreakIteration, state.LowestBreakIteration.Value);
//}
FileSearchResult result = new FileSearchResult(ix, file);
for (int i = 0; i < results.Count; ++i)
{
if (state.ShouldExitCurrentIteration)
{
return;
}
var regexMatch = results[i];
SearchMatch match = new SearchMatch();
match.Index = regexMatch.Index;
match.Length = regexMatch.Length;
result.Matches.Add(match);
}
if (state.ShouldExitCurrentIteration)
{
return;
}
matchesList.Add(result);
}
);
return matchesList.ToArray();
}
public FileSearchResult[] SearchInFiles(string query, string sourceFolderPath)
{
if (string.IsNullOrWhiteSpace(sourceFolderPath) || !Directory.Exists(sourceFolderPath))
{
return Array.Empty<FileSearchResult>();
}
string[] filePathList = Directory.GetFiles(sourceFolderPath);
return SearchInFiles(query, filePathList);
}
В принципе, он работает, но если я ищу слово во всех файлах, этот метод должен возвращать только 1-й найденный элемент, вместо этогоЯ получаю 2, а иногда и 3 предмета.Если я отлаживаю вызов на state.Break();
, я вижу, что иногда он вызывается более одного раза.Что я делаю не так?