Проблема в параллельном foreach относительно Regex - PullRequest
0 голосов
/ 17 мая 2018

Мне нужна помощь в преобразовании этого цикла for в параллельный цикл.

public void spellchecker()
{
    Invoke(new MethodInvoker(delegate ()
    {       
        using (Hunspell hunspell = new Hunspell("en_us.aff", "en_US.dic"))
        {
            foreach (Match match in Regex.Matches(GetRichTextBox().Text, @"\w+"))
            {
                string word = match.Value;
                Font fnt = GetRichTextBox().Font;
                Color color;
                if (!hunspell.Spell(word))
                {
                    fnt = new Font(fnt.FontFamily, fnt.Size, FontStyle.Underline);
                    color = Color.Red;
                }
                else
                {
                    fnt = new Font(fnt.FontFamily, fnt.Size, FontStyle.Regular);
                    color = Color.Black;
                }

                GetRichTextBox().Select(match.Index, match.Length); // Selecting the matching word.
                GetRichTextBox().SelectionColor = color;
                GetRichTextBox().SelectionStart = GetRichTextBox().TextLength; // Resetting the selection.
                GetRichTextBox().SelectionLength = 0;
            }                            
        }
    }));


}

Это была моя реализация, когда я пытался реализовать параллельный цикл for.Я все время получаю сообщение об ошибке "Arguments for method'Parallel.ForEach<TSource>(IEnumereable<TSourcce>,Action<TSource>) 'не может быть выведено из использования"

Parallel.ForEach(Regex.Matches(GetRichTextBox().Text, @"\w+"), match => {
    string word = match.Value;
    Font fnt = GetRichTextBox().Font;
    Color color;
    if (!hunspell.Spell(word))
    {
        fnt = new Font(fnt.FontFamily, fnt.Size, FontStyle.Underline);
        color = Color.Red;
    }
    else
    {
        fnt = new Font(fnt.FontFamily, fnt.Size, FontStyle.Regular);
        color = Color.Black;
    }

    GetRichTextBox().Select(match.Index, match.Length); // Selecting the matching word.
    GetRichTextBox().SelectionColor = color;
    GetRichTextBox().SelectionStart = GetRichTextBox().TextLength; // Resetting the selection.
    GetRichTextBox().SelectionLength = 0;
});

1 Ответ

0 голосов
/ 17 мая 2018

Parallel.ForEach () хочет IEnumerable<T> для своего первого параметра.TSource должно быть выведено из этого аргумента типа, потому что второй параметр является лямбда-выражением без объявленного типа для своего собственного параметра. Regex.Matches (строка, строка) возвращает MatchCollection, что реализует неуниверсальные System.Collections.IEnumerable, , а не IEnumerable<T>.Это предшествует дженерикам.Таким образом, компилятор не может сделать вывод, что такое TSource.

Но мы знаем, TSource должно быть Match.Поэтому используйте Cast<T>():

Parallel.ForEach(Regex.Matches(GetRichTextBox().Text, @"\w+").Cast<Match>(), 
    match => {

Достопримечательности

Можно прямо сказать, что параметр лямбды равен Match:

Parallel.ForEach(Regex.Matches(GetRichTextBox().Text, @"\w+"), (Match match) =>

Ивы больше не получите ошибку вывода типа.Однако вы все равно получите сообщение об ошибке IEnumerable, поскольку MatchCollection по-прежнему не реализует универсальную IEnumerable<T>:

ошибка CS1503: Аргумент 1: невозможно преобразовать из 'System.Text.RegularExpressions.MatchCollection 'to' System.Collections.Generic.IEnumerable<System.Text.RegularExpressions.Match> '


Кстати, именно поэтому вы не можете использовать var в foreach на MatchCollection без явного объявления переменной циклакак Match или приведение его в теле цикла: На основании всего, что знает компилятор, m равно object.

foreach (var m in Regex.Matches("foo", "[0-9]"))
{
    var caps = m.Captures;
}

ошибка CS1061: «объект» не содержит определения для «Captures» и не может быть найден метод расширения «Captures», принимающий первый аргумент типа «object» (вы пропустилидиректива об использовании или ссылка на сборку?)

...