2

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

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

性能分析表明问题是 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 的性能,回收“范围”对象或类似的东西?还有什么其他解决方案。

4

1 回答 1

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

(注意在决定是否初始化变量之前检查空引用并不像TextRange在声明中实例化 a 那样简洁。不幸的是,TextRange没有公共的空构造函数,也TextPointer没有公共构造函数。你可以用一些虚拟值创建它您的类构造函数以避免此检查。)

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

假设您不colorInterval从多个线程调用,我会说这是一种比您目前节省时间更好的方法,因为(我猜想)colorInterval经常被调用并且后续TextRange对象的持续创建和垃圾收集它留下的肯定是一种低效率。

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

Naturally, there will be some work here because any change is unlikely to completely encapsulate a highlighted range. The TextRange class has a method for finding the paragraphs in which the start and end of a range can be found, in case that helps. There's probably a case for storing details of each highlighted range so you can quickly check for intersection.

于 2012-07-25T13:11:39.117 回答