2

私は現在、構文の強調表示とコード補完プロジェクトに取り組んでおり、RichTextBox に基づくユーザー コントロールを作成しています。RTB の動作方法やすべてに適応するのにいくつか問題がありましたが、単純な構文の強調表示を行うことができました。

シンプルとは、ユーザーが文字を入力するたびにテキスト全体を強調表示することを意味します。速すぎてはいけませんが、遅すぎます。約 500 文字相当のテキストがあり、入力した文字ごとにテキストを 1 回だけ通過させると、パフォーマンスの問題が明らかになります (「colorInterval」関数は 1 回のパスで約 100 回呼び出されます)。

パフォーマンス分析によると、問題は約 80% 以上の時間を要する TextRange コンストラクターであり、テキストの間隔に色を付ける必要があるたびに使用します。

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は読み取り専用ですが、使用しているコンストラクターと同じように2つのオブジェクトを取得して、両方を更新するパブリックメソッドがありますSelectTextPointer

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、宣言でaをインスタンス化するほどきれいではありません。残念ながら、TextRangeパブリックの空のコンストラクターTextPointerもパブリックのコンストラクターもありません。いくつかのダミー値を使用して作成できます。このチェックを回避するためのクラスコンストラクタ。)

上で、「それが本当にコンストラクターであるかどうか」と言いました。明らかに、あなたが正しく行ったプロファイリングはコンストラクターを強調していますが、それはコンストラクターとSelectメソッドに共通のルーチンである可能性もあります。

colorInterval複数のスレッドから呼び出さないと仮定すると、これは現在の時間節約よりも優れたアプローチだと思います。これは、(おそらく)頻繁に呼び出され、後続のオブジェクトcolorIntervalの継続的な作成とガベージコレクションが行われるためです。TextRangeそれが残すのは確かに非効率です。

この提案を行ったので、(たとえば)1つの文字の変更に対応するたびに、ドキュメント全体をスキャンするモデルから離れることを強くお勧めします。> = .net 3.5をターゲットにしていると仮定すると、は、変更の場所(および変更によって追加または削除された文字)を計算できるオブジェクトのリストを報告するイベントをRichTextBox提供します。TextChangedTextChange

当然のことながら、ハイライトされた範囲を完全にカプセル化する変更はほとんどないため、ここでいくつかの作業が行われます。このTextRangeクラスには、役立つ場合に備えて、範囲の開始と終了を見つけることができる段落を見つけるためのメソッドがあります。強調表示された各範囲の詳細を保存して、交差点をすばやく確認できる場合があります。

于 2012-07-25T13:11:39.117 に答える