15 WPFパフォーマンスのヒント
あなたはWPF開発者ですか?ここでは、WPF アプリケーションのパフォーマンスを特定して改善するための 15 のヒントを紹介します。続きを読む。
あなたはWPF開発者ですか?WPF アプリのパフォーマンスが低い領域や、期待どおりに実行されない領域はありませんか? もしそうなら、WPF アプリケーションのパフォーマンスを特定して改善するのに役立つ 15 ヒントがあります。
WPF は 10 年以上前のもので、長年にわたって大幅に改善されてきましたが、パフォーマンスの低下に悩まされる可能性のある領域がまだいくつかあります。 このパフォーマンスの低下の理由には、不適切なコーディング手法、壊れたバインディング、複雑なレイアウト、UI仮想化の欠如などが含まれます。さいわい、少し計画を立てて WPF プラットフォームをしっかりと理解すれば、WPF アプリケーションをワープ スピードで跳躍させ、ミリ秒単位で宇宙を飛び越えることができます。
WPF アプリのパフォーマンスを向上させるのに役立つ 15 のヒントをまとめました。
1. ビジュアルツリーをシンプルにする
パフォーマンスの問題の一般的な原因は、深く複雑なレイアウトです。XAML マークアップは、できるだけシンプルで浅いものにしてください。UI 要素が画面上に描画されると、要素ごとに "レイアウト パス" が 2 回呼び出されます (メジャー パスとアレンジ パス)。レイアウト パスは数学的に負荷の高いプロセスであり、要素内の子の数が多いほど、必要な計算の数が多くなります。
2. ItemsControls を仮想化する
前述のように、複雑で深いビジュアル ツリーは、メモリ フットプリントが大きくなり、パフォーマンスが低下します。ItemsControls は、仮想化されていないため、通常、深いビジュアル ツリーでパフォーマンスの問題が増加します。これは、コントロール内の各項目に対して常に作成および破棄されていることを意味します。代わりに、VirtualizingStackPanel を項目ホストとして使用し、VirtualizingStackPanel.IsVirtualizing を使用して VirtualizationMode を Recycling に設定すると、項目コンテナを毎回新しいコンテナを作成するのではなく、再利用できます。
3. DynamicResources よりも StaticResources を優先する
StaticResources は、既に定義されているリソースへの参照を検索することで、任意の XAML プロパティ属性の値を提供します。そのリソースの検索動作は、コンパイル時の検索と同じです。DynamicResources は一時的な式を作成し、要求されたリソース値が必要になるまでリソースの検索を延期します。そのリソースの検索動作は実行時の検索と同じであり、パフォーマンスに影響が及びます。可能な限り、常に StaticResource を使用してください。
4.要素の代わりにブラシの不透明度
ブラシを使用して要素の Fill または Stroke を設定する場合は、要素の Opacity プロパティを設定するよりも、Brush の Opacity を設定する方が適切です。要素の Opacity プロパティを変更すると、WPF で一時的なサーフェスが作成され、パフォーマンスが低下する可能性があります。
5. Avoid Using Run to Set Text Properties
TextBlock 内で Runs を使用すると、パフォーマンスを集中的に使用する操作が大幅に高くなるため、使用しないでください。Run を使用してテキスト プロパティを設定している場合は、代わりに TextBlock で直接設定します。
6. Favor StreamGeometries over PathGeometries
StreamGeometry オブジェクトは、PathGeometry の非常に軽量な代替手段です。StreamGeometry は、多くの PathGeometry オブジェクトを処理するために最適化されています。メモリの消費が少なく、多くの PathGeometry オブジェクトを使用する場合に比べてパフォーマンスが大幅に向上します。
7. Use Reduced Image Sizes
アプリで小さいサムネイルを表示する必要がある場合は、画像の縮小サイズ バージョンを作成することを検討してください。既定では、WPF はイメージを読み込み、フル サイズにデコードします。これは、完全なイメージを読み込み、ItemsControl などのコントロールでサムネイル サイズに縮小する場合に、多くのパフォーマンスの問題の原因となる可能性があります。可能であれば、複数の画像で構成されるフィルムストリップなど、すべての画像を 1 つの画像に結合します。
8. Lower the BitMapScalingMode
既定では、WPF は高品質のイメージ再サンプリング アルゴリズムを使用しますが、システム リソースが消費され、フレーム レートが低下したり、アニメーションが途切れたりすることがあります。代わりに、BitMapScalingMode を LowQuality に設定して、"品質最適化" アルゴリズムから "速度最適化" アルゴリズムに切り替えます。
9.冷凍庫の使用と凍結
Freezable は、凍結解除と凍結の 2 つの状態を持つ特殊なタイプのオブジェクトです。ブラシやジオメトリなどのオブジェクトをフリーズすると、そのオブジェクトは変更できなくなります。可能な限りオブジェクトをフリーズすると、アプリケーションのパフォーマンスが向上し、メモリ消費量が削減されます。
10. Fix your Binding Errors
バインディング エラーは、WPF アプリで最も一般的なパフォーマンスの問題の種類です。バインディング エラーが発生するたびに、アプリはパフォーマンス ヒットを受け、バインディングの解決を試みてエラーをトレース ログに書き込みます。ご想像のとおり、バインディング エラーが多ければ多いほど、アプリのパフォーマンスへの影響は大きくなります。時間をかけて、すべてのバインディングエラーを見つけて修正してください。DataTemplate で RelativeSource バインディングを使用すると、通常、DataTempate が初期化を完了するまでバインディングが適切に解決されないため、バインディング エラーの主な原因となります。RelativeSource.FindAncestor の使用は絶対に避けてください。代わりに、添付プロパティを定義し、プロパティの継承を使用して、ビジュアル ツリーを検索する代わりに、ビジュアル ツリーに値をプッシュします。
11. Label.Content プロパティへのデータバインディングを避ける
Label to data bind to a String プロパティを使用している場合、パフォーマンスが低下します。これは、String ソースが更新されるたびに、古い String オブジェクトが破棄され、新しい String が作成されるためです。Label の Content が単純なテキストの場合は、TextBlock に置き換えて、代わりに Text プロパティにバインドします。
12. Bind ItemsControls to IList instead of IEnumerable
ItemsControl を IEnumerable にデータ バインドすると、WPF は IList<T 型のラッパーを作成します。これは>2 番目のオブジェクトの作成によるパフォーマンスに悪影響を及ぼします。代わりに、ItemsControl を直接 IList にバインドして、ラッパー オブジェクトのオーバーヘッドを回避します。
13. Use the NeutralResourcesLanguage Attribute
NeutralResourcesLanguageAttribute を使用して、ニュートラル カルチャが何であるかを ResourceManager に伝え、サテライト アセンブリの検索の失敗を回避します。
14. 別々のスレッドでデータをロードする
パフォーマンスの問題、UI のフリーズ、アプリの応答停止の原因として非常に多いのは、データの読み込み方法です。UI スレッドが過負荷にならないように、データを別のスレッドに非同期的に読み込んでいることを確認してください。UI スレッドにデータを読み込むと、パフォーマンスが非常に低下し、エンドユーザー エクスペリエンスが全体的に低下します。マルチスレッドは、すべての WPF 開発者がアプリケーションで使用するものであるべきです。
15. Beware of Memory Leaks
メモリ リークは、ほとんどの WPF アプリケーションのパフォーマンスの問題の最大の原因です。 それらは簡単に手に入れることができますが、見つけるのは難しい場合があります。 たとえば、DependencyPropertyDescriptor.AddValueChanged を使用すると、WPF フレームワークは、手動で DependencyPropertyDescriptor.RemoveValueChanged を呼び出すまで削除されないイベントのソースへの強い参照を取得する可能性があります。ビューや動作がオブジェクトまたはビューモデルから発生するイベント(INotifyPropertyChanged など)に依存している場合は、それらを弱くサブスクライブするか、手動でサブスクライブ解除していることを確認してください。また、INotifyPropertyChanged を実装していない ViewModel のプロパティにバインドしている場合は、メモリ リークが発生している可能性があります。
最後に、ボーナスのヒントです。パフォーマンスの問題が発生した場合、問題の原因を正確に特定するのが非常に難しい場合があります。アプリケーション パフォーマンス プロファイラーを使用して、これらのパフォーマンスのボトルネックがコード ベースのどこで発生しているかを特定することをお勧めします。利用可能なプロファイラー オプションはたくさんあります。有料のものもあれば、無料のものもあります。私が個人的に最もよく使用するのは、Visual Studio 2019に直接組み込まれている診断ツールです。
Twitterで私と交流し、私のYouTubeチャンネルに登録して新しいビデオコンテンツの通知を受け取り、Twitchで私をフォローしてライブストリームをご覧ください。また、Ultimate UI for WPFを使用している場合は、コミュニティフォーラムを通じてさまざまなチームとつながり、インフラジスティックスのエンジニアや他の顧客と交流することができます。