2016-05-30 7 views
1

私はWindows Forms開発者であり、現在WPFで忙しいです。テキストボックスのテキストレンダリングに関する2つの技術のパフォーマンス比較をすばやく行うために、私はウィンドウ内に膨大な数のテキストボックスを作成し、100msごとにテキストを更新する小さなプログラムを作成しました。多くのテキストボックスを使用したテキストのレンダリングが遅い

私の驚いたことに、テストアプリケーションのWPFバージョンは、WinFormsバージョンよりもはるかに低速です。ほとんどの場合、アプリケーションが応答しません。たとえば、ウィンドウのサイズを変更しようとしたときなどです。アプリケーションのWinFormsバージョンは円滑に実行されます。

私の質問は:WPFコントロールを使用する方法に問題がありますか(WPFのコントロールコンテナとしてWrapPanelを使用し、WinFormsのFlowLayoutPanelを使用します)。または、WinFormsよりも実際にテキストのレンダリングが遅いですか?

WPF:

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Threading; 

namespace PerformanceTestWPF 
{ 
    public partial class MainWindow : Window 
    { 
     DispatcherTimer _timer = new DispatcherTimer(); 
     Random _r = new Random(); 

     public MainWindow() 
     { 
      InitializeComponent(); 

      for (int i = 0; i < 400; i++) 
       this.wrapPanel.Children.Add(new TextBox {Height = 23, Width = 120, Text = "TextBox"}); 

      _timer.Interval = new TimeSpan(0,0,0,0, 100); 
      _timer.Tick += _timer_Tick; 
      _timer.Start(); 

     } 

     private void _timer_Tick(object sender, EventArgs e) 
     { 
      foreach (var child in wrapPanel.Children) 
      { 
       var textBox = child as TextBox; 
       if (textBox != null) 
       { 
        textBox.Text = _r.Next(0, 1000).ToString(); 
       } 
      } 
     } 
    } 
} 

リサイズ:

using System; 
using System.Windows.Forms; 

namespace PerformanceTestWinforms 
{ 
    public partial class Form1 : Form 
    { 
     Timer _timer = new Timer(); 
     Random _r = new Random(); 

     public Form1() 
     { 
      InitializeComponent(); 

      for (int i = 0; i < 400; i++) 
       this.flowLayoutPanel1.Controls.Add(new TextBox { Height = 23, Width = 120, Text = "TextBox" }); 

      _timer.Interval = 100; 
      _timer.Tick += _timer_Tick; 
      _timer.Start(); 
     } 

     private void _timer_Tick(object sender, EventArgs e) 
     { 
      foreach (var child in flowLayoutPanel1.Controls) 
      { 
       var textBox = child as TextBox; 
       if (textBox != null) 
       { 
        textBox.Text = _r.Next(0, 1000).ToString(); 
       } 
      } 
     } 
    } 
} 
+0

結論にジャンプしません。高価なディスパッチャのサイクルかもしれません。私のマシンでプロファイリングができません(より高い資格情報が必要です)。どの機能が実際にボトルネックであるかを知るためにそれを実行できるかどうかを確認してください。 –

答えて

2

私はこの結合ベースの例しようと、問題は明示的なディスパッチだと思う:それはまだ非常に窒息だリサイズ時には

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Windows.Threading; 

namespace WpfPerfTest 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     Timer _timer; 
     Random _r = new Random(); 

     private readonly List<ValueViewModel<string>> _values = new List<ValueViewModel<string>>(); 

     public MainWindow() 
     { 
      InitializeComponent(); 

      for (int i = 0; i < 400; i++) 
      { 
       var value = new ValueViewModel<string>(); 
       var tb = new TextBox { Height = 23, Width = 120 }; 
       tb.SetBinding(TextBox.TextProperty, new Binding("Value") { Source = value }); 
       this.wrapPanel.Children.Add(tb); 
       this._values.Add(value); 
      } 

      _timer = new Timer(o => 
      { 
       foreach (var value in this._values) 
        value.Value = _r.Next(0, 1000).ToString(); 
      }, null, 0, 100); 
     } 
    } 

    class ValueViewModel<T> : INotifyPropertyChanged where T : class 
    { 

     private T _Value = default(T); 
     public T Value 
     { 
      get { return _Value; } 
      set 
      { 
       if (value != _Value) 
       { 
        _Value = value; 
        OnPropertyChanged("Value"); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 


     protected virtual void OnPropertyChanged(string name) 
     { 
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 

をちょっとしたことだけど、それ以外ははるかに優れている。

+0

ありがとう、これは本当にはるかに優れています。しかし、なぜここでより高速にディスパッチしているのですか(タイマーは非同期にコールバックを実行するSystem.Threading.Timerなので、何らかの暗黙的なディスパッチが起こっていると思います)。 – loki

+0

バインディングを使用すると、ディスパッチは暗黙的に行われるため、おそらくより効率的にスケジュールされるか、更新は既存のループにマージされます。 WPFディスパッチャの内部構造はかなり複雑です。詳細については[この記事](https://msdn.microsoft.com/en-us/library/ms741870%28vs.100%29.aspx)をお勧めします。 –

関連する問題