RichTextBox中的TextRange构造函数性能

时间:2012-07-25 11:03:06

标签: c# wpf textrange

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

简单意味着每次用户键入字符时都会突出显示整个文本。它不应该是快速或任何东西,但它太慢。当我有大约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的性能,回收'范围'对象或类似的东西?还有哪些其他解决方案。

1 个答案:

答案 0 :(得分:1)

最简单的方法是(按照你的建议)重用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);
  ...
}

(NB在确定是否初始化变量之前检查空引用并不像在声明中实例化TextRange那样整洁。不幸的是,TextRange没有公共空构造函数和{{ 1}}根本没有公共构造函数。你可以在类构造函数中创建一些虚拟值来避免这种检查。)

上面,我说'如果它真的是构造函数'。显然,你正确完成的分析突出了构造函数,但它可以很容易地成为构造函数和TextPointer方法的常用例程。

假设你没有从多个线程中调用Select,我会说这是一个比现在更好的方法,因为(我猜)colorInterval是经常被调用,它留下的后续colorInterval对象的不断创建和垃圾收集肯定是效率低下的。

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

当然,这里会有一些工作,因为任何改变都不可能完全封装突出显示的范围。 TextChange类有一个方法可以找到可以找到范围的开头和结尾的段落,如果有帮助的话。可能存在每个突出显示范围的详细信息,以便您可以快速检查交叉点。