RichTextBox中的TextRange构造函数性能



我目前正在进行语法高亮显示和代码完成项目,并基于RichTextBox进行用户控制。我在适应RTB的工作方式和其他方面遇到了一些问题,但我已经设法进行了简单的语法高亮显示。

Simple意味着每次用户键入字符时,我都会突出显示整个文本。它不应该很快,但它太慢了。当我有大约500个字符的文本时,性能问题就会变得明显,并且我只对每个键入的字符进行一次文本传递("colorInterval"函数在一次传递中被调用大约100次)。

性能分析表明,问题是TextRange构造函数占用了大约80%以上的时间,每次我需要为文本间隔着色时都会使用它:

private void colorInterval(TextPointer start, TextPointer end)
    {
        TextRange range = new TextRange(start, end);
        if(isFunction(range.Text)) colorAsFunction(range);
        if(isInQuotes(range.Text)) colorAsQuoted(range);
        ...
    }

下面是我的问题:

我这样做是不是做错了什么,或者有没有办法提高TextRange的性能,回收"range"对象之类的东西?还有什么其他解决方案。

最简单的方法是(正如您所建议的)重用TextRange对象,如果它确实是占用您大部分时间的构造函数。TextRange属性StartEnd是只读的,但有一个公共方法Select将同时更新这两个属性,采用两个TextPointer对象,就像您一直使用的构造函数一样。

protected TextRange range;
private void colorInterval(TextPointer start, TextPointer end)
{
  if (range == null)
    range = new TextRange(start, end);
  else
    range.Select(start, end);
  ...
}

(注意:在决定是否初始化变量之前检查null引用并不像在声明中实例化TextRange那么简单。不幸的是,TextRange没有公共空构造函数,TextPointer根本没有公共构造函数。你可以在类构造函数中使用一些伪值来创建它,以避免这种检查。)

上面,我说"如果它真的是构造函数"。显然,您所做的评测突出显示了构造函数,但它也可以很容易地成为构造函数和Select方法的通用例程。

假设您不从多个线程调用colorInterval,无论节省多少时间,我都认为这是一种比当前更好的方法,因为(我猜)colorInterval被频繁调用,并且它留下的后续TextRange对象的不断创建和垃圾收集肯定是低效的。

提出这个建议后,我强烈建议您放弃每次想要对(例如)单个字符的更改做出反应时都要扫描整个文档的模式。假设您的目标是>=.net 3.5,RichTextBox将提供一个TextChanged事件,该事件报告TextChange对象的列表,您可以从中计算出更改的位置(以及添加或删除的字符)。

当然,这里会有一些工作,因为任何更改都不太可能完全封装突出显示的范围。TextRange类有一个方法,用于查找可以找到范围的开始和结束的段落,以防有帮助。可能存在存储每个高亮显示范围的详细信息的情况,这样您就可以快速检查交叉点。

相关内容

  • 没有找到相关文章

最新更新