Почему класс Parallel не останавливается при вызове .Break () - PullRequest
0 голосов
/ 30 марта 2019

Мне нужно найти подстроку в более чем 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();, я вижу, что иногда он вызывается более одного раза.Что я делаю не так?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...