【问题标题】:Issue in Parallel foreach regarding Regex关于正则表达式的并行 foreach 问题
【发布时间】:2018-05-17 16:05:39
【问题描述】:

我需要帮助才能将此 for 循环转换为并行 forloop。

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;
});

【问题讨论】:

  • 尝试 GetRichTextBox<String>() 并将 lambda 转换为 Action<String>

标签: c# task-parallel-library parallel.foreach


【解决方案1】:

Parallel.ForEach() 需要IEnumerable<T> 作为它的第一个参数。 TSource 必须从该类型参数中推断出来,因为第二个参数是一个 lambda 表达式,它自己的参数没有声明类型。 Regex.Matches(string, string) 返回 MatchCollection,实现非泛型 System.Collections.IEnumerablenot IEnumerable<T>。它早于泛型。所以编译器无法推断TSource 是什么。

但我们知道TSource 应该是Match。所以使用Cast<T>():

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

兴趣点

你可以明确地说 lambda 的参数是Match

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

您将不再收到类型推断错误。但是,您仍然会收到有关 IEnumerable 的错误,因为 MatchCollection 仍然不会实现通用 IEnumerable&lt;T&gt;

错误 CS1503:参数 1:无法从“System.Text.RegularExpressions.MatchCollection”转换为“System.Collections.Generic.IEnumerable&lt;System.Text.RegularExpressions.Match&gt;


顺便说一句,这就是为什么您不能在 MatchCollection 上的 foreach 中使用 var 而不将循环变量明确声明为 Match 或将其强制转换为循环主体:根据编译器所知道的一切, mobject

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

错误 CS1061:“object”不包含“Captures”的定义,并且找不到接受“object”类型的第一个参数的扩展方法“Captures”(您是否缺少 using 指令或程序集引用?)

【讨论】:

    猜你喜欢
    • 2019-08-27
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 2011-11-14
    • 2021-03-06
    • 2016-12-22
    相关资源
    最近更新 更多