【问题标题】:Syntax Highlighting performance issue语法突出显示性能问题
【发布时间】:2015-05-11 20:01:13
【问题描述】:

我有一个 RichTextBox,一旦用户加载一个文件,我的程序就会继续扫描整个文件以更改某些单词的颜色。这是我的代码:

static Regex cKeyWords = new Regex(@"\b(?=[a-gilr-w])(?:
     s(?:hort|i(?:gned|zeof)|t(?:atic|ruct)|witch) | c(?:ase|har|on(?:st|tinue)) |
     e(?:lse|num|xtern) | i(?:f|nt) | f(?:loat|or) | d(?:o|efault|ouble) | un(?:ion|signed) |
     re(?:gister|turn) | vo(?:id|latile) | while | break | long | typedef | auto | goto
     )\b",
     RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);

...

programTextBox.Enabled = false;
int selectStart = this.programTextBox.SelectionStart;
programTextBox.SuspendLayout();
MatchCollection matches = cKeyWords.Matches(programTextBox.Text);
foreach (Match match in matches)
{
    if (match.Index == 0)
        programTextBox.Select(match.Index, match.Length/* - 1*/);
    else
        programTextBox.Select(match.Index + 1, match.Length - 1);
    programTextBox.SelectionColor = Color.Blue;
}
programTextBox.Select(selectStart, 0);
programTextBox.SelectionColor = Color.Black;
programTextBox.Enabled = true;
programTextBox.ResumeLayout();

问题:我的代码需要大约 5 秒半的时间来扫描并更改包含 200,000 个字符的文件中所有关键字的颜色。

之前有人告诉我,我不应该将正则表达式用于那种东西,但在做了几次测试后,我发现:MatchCollection matches = cKeyWords.Matches(programTextBox.Text);

只需要大约 0.1s 和删除

programTextBox.SelectionColor = Color.Blue;

将我的代码的总执行时间从 5.5s 减少到大约 0.3s

怎么样?为什么?最重要的是:我能做什么?

【问题讨论】:

  • 哦,是的,忘记提了。是的。
  • RichTextBox 不是特别有效。您可以尝试通过自己构建 RTF 来应用语法突出显示:rtf spec。将结果分配给文本框的Rtf 属性。
  • 在循环之前暂停绘画并在循环之后立即恢复。 stackoverflow.com/questions/3282384/… 或更好地找到支持语法高亮的控件。有几个可用的开源库。
  • 暂停布局并在你完成更改后像@SriramSakthivel 建议的那样恢复,然后调用 RichTextbox.Refresh()。这将仅绘制可见项目。我是为我的 datagridview 项目做的,节省了很多时间。

标签: c# regex winforms richtextbox syntax-highlighting


【解决方案1】:

我维护 VS Code 的 C++ 语法高亮显示,它有超过 9000 个字符的 single regex patterns。您编写的正则表达式非常有效,可能效率过高(删除前瞻比分解单词更有帮助)。

这是一个基本的 UI 问题。 UI 很慢,像 VS Code 这样的东西无法在一秒钟内突出显示 200,000 行。这很好,因为用户永远不会同时查看 200,000 行。因此,Atom/VS Code 智能地只为可见的行调用等效的 programTextBox.SelectionColor = Color.Blue;。与 Sublime 和其他文本编辑器相同;他们只更新你看到的和改变了什么,因为弄乱 GUI 是非常昂贵的。

不要更新 UI 约 100,000 次,而是按照 Sriram Sakthivel 的评论所说的(不知道他为什么没有回答)“在循环之前暂停绘画并在循环之后立即恢复。RichTextBox syntax highlighting in real time--Disabling the repaint 或更好找到一个支持语法高亮的控件。有几个可用的开源库。"

这实际上是用于每个文本编辑器的相同解决方案。

【讨论】:

    【解决方案2】:

    你试过this吗?

    这会阻止绘画,实际上似乎可以正确阻止它。我只有一个小测试文件可以通过它,但它似乎工作得很好。

    【讨论】:

      【解决方案3】:

      尝试使用 SharpDevelop IDE 的语法高亮编辑器 ICSharpCode.TextEditor,而不是自己进行语法高亮显示。

      【讨论】:

      • 请发表答案,然后参考。
      猜你喜欢
      • 2021-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-14
      • 1970-01-01
      • 2017-08-17
      • 2019-06-14
      相关资源
      最近更新 更多