2016-10-04 6 views
10

私は最近UserControlRichTextBoxPreviewTextInputPreviewMouseUpのようなカップルイベントを持つ単純なRTFエディタを開発しています。RichTextBox - UIのサイズ変更によって膨大なCPU負荷が発生する

私は少し気になりました。 RichTextBoxのパフォーマンスは、UIのサイズが変更され、RichTextBoxにはラッピングアルゴリズムを起動させるテキストがたくさんあるときはいつもひどいです。

これは、あまり最適化されていない(たとえそうでなくても)かのように、アプリケーションに本当にかすかな感触を与えます。

最初に、テキストを選択しているときにこのパフォーマンスヒットが発生したので、SelectionChangedイベントを使用する代わりに、PreviewMouseUpイベントを使用して選択をフェッチしました。

さらにテストした結果、サイズ変更によっても大きな負荷が発生することがわかりました。 そして、3.8GHzで動作するクアッドコアCPUを搭載した負荷が5%〜30%の範囲で話しています。

はさらにそれをテストするために、私は私のRichTextBoxをコメントアウトすることを決めただけではありません定義されたプロパティ

<RichTextBox/> 

、ウィンドウにこれを挿入するテキストを充填した後にウィンドウのサイズを変更して新しいRichTextBoxを含めますラッピングアルゴリズムが30%の使用量まで同じように再現されました。

私はこの問題について調査してみました、そしてほとんどの人は、ラッピングを防止するために、高い値にPageWidthを設定推薦することになった:

私はエディタの以前のバージョンから、したくない
richTextBox1.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible; 
richTextBox1.Document.PageWidth = 1000; 

私はWinFormsを使って作成したものであり、簡単に折り返しを行うことができました。また、新しいWPFバージョンでも使用したいと思います。

誰もこの問題に直面しましたか? もしそうなら、正しい方向にハードウェア上のこの大きな歪みを取り除くことを教えてください。

私はWPFが大好きなのでちょっと悲しいですが、実際には最適化されていない、またはWinFormsに比べて実用的でないオブジェクトが見つかりました。RichTextBoxは、これらのケースのもう1つのようです:(

テキストの膨大な量のために申し訳ありませんが、私は本当にこれがきちんと場合には他のいくつかの貧しい人々の魂がこの問題に直面し、あなたたちは、私がこれまで試したかを確認するために文書化したいと思った。

答えて

7

ワンこの問題を克服する方法は、ウインドウのサイズを変更しているときにユーザーがリサイズを完了したときに「折り返しなし」モードに切り替えることです。通常モードに戻してから、折り返しアルゴリズムを最後に1回実行します。 sersはあなたのアプリケーションについてまだ滑らかな感覚を持っているはずです。サンプルコード:

public partial class MainWindow : Window 
{ 
    public MainWindow() { 
     InitializeComponent(); 
     this.SizeChanged += OnSizeChanged; 
    } 

    private Timer _timer; 
    private void OnSizeChanged(object sender, SizeChangedEventArgs e) { 
     // user started resizing - set large page width 
     textBox.Document.PageWidth = 1000; 
     // if we already setup timer - stop it and start all over 
     if (_timer != null) { 
      _timer.Dispose(); 
      _timer = null; 
     } 

     _timer = new Timer(_ => { 
      // this code will run 100ms after user _stopped_ resizing 
      Dispatcher.Invoke(() => 
      { 
       // reset page width back to allow wrapping algorithm to execute 
       textBox.Document.PageWidth = double.NaN; 
      }); 
     }, null, 100, Timeout.Infinite); 
    } 
} 
+0

私がResize Callを取得している明らかな選択方法については面白くないと思いますが、私はあまりにも疲れていると思います。あなたのコードにbtwを呼び出そうとしているところにエラーがあります。以下はそれを修正します:Dispatcher。呼び出し(新しいアクション(()=> {})); –

+0

ちなみに、PCのパフォーマンスによっては、実際にはイベントがサイズ変更されているかどうかはわかりませんが、私の場合は300msを多かれ少なかれ使用しなければならないため、Timersを使用するのは危険です。それは間違いなく正しい方向に私を指摘し、私は自分の必要性に合わせてそれを変更し、最終的にタイマーを取り除くつもりです。ありがとう。 –

+0

また、パフォーマンス上の理由を知ることに興味があれば、これは50%のオーバーヘッドを減らすのに役立ちましたが、多くのテキストが内部にある場合はサイズを変更しながら15%の使用率になりました。IMO RichTextBoxは面倒なこれは、ラップアルゴリズムがこれらの問題の原因となっている唯一の要因ではないように思われるからです。私は正しい方向に向いてくれてありがとうございます;) –