パフォーマンスの最適化: アプリケーション リソース

WPF を使用すると、類似した型の要素全体で一貫した外観や動作をサポートできるように、アプリケーション リソースを共有できます。 このトピックでは、アプリケーションのパフォーマンスを向上させるために役立ついくつかの推奨事項について説明します。

リソースについて詳しくは、「XAML リソース」をご覧ください。

リソースを共有する

アプリケーションでカスタム コントロールを使用して、ResourceDictionary (または XAML リソース ノード) 内のリソースを定義する場合は、Application または Window のオブジェクト レベルでリソースを定義するか、カスタム コントロールの既定のテーマでそれらを定義することをお勧めします。 カスタム コントロールの ResourceDictionary にリソースを定義すると、そのコントロールのすべてのインスタンスのパフォーマンスに影響が生じます。 たとえば、カスタム コントロールのリソース定義の一部として定義されたパフォーマンス重視のブラシ操作と、カスタム コントロールの多数のインスタンスがある場合、アプリケーションのワーキング セットは大幅に増加します。

この点について説明するために、次のように考えてみます。 たとえば、WPF を使用してカード ゲームを開発しているとします。 ほとんどのカード ゲームでは、52 個の異なる表を持つ 52 枚のカードが必要です。 カードのカスタム コントロールを実装し、カードのカスタム コントロールのリソースに 52 個のブラシ (それぞれカードの表を表す) を定義します。 メイン アプリケーションでは、最初にこのカード カスタム コントロールのインスタンスを 52 個作成します。 カード カスタム コントロールの各インスタンスで、Brush オブジェクトのインスタンスが 52 個生成されます。これにより、アプリケーションで合計 52 * 52 個の Brush オブジェクトが得られます。 カード コントロールの 52 個のインスタンス間で 52 個のブラシを共有しているため、ブラシをカードのカスタム コントロール リソースから Application または Window オブジェクト レベルに移動するか、カスタム コントロールの既定のテーマで定義することで、アプリケーションのワーキング セットを減らすことができます。

ブラシをコピーせずに共有する

同じ Brush オブジェクトを使用している複数の要素がある場合は、XAML でブラシをインラインで定義するのではなく、ブラシをリソースとして定義し、それを参照します。 この方法では、1 つのインスタンスを作成して再利用します。一方、XAML でブラシをインラインで定義すると、要素ごとに新しいインスタンスが作成されます。

次のマークアップ サンプルは、この点を示しています。

<StackPanel.Resources>
  <LinearGradientBrush x:Key="myBrush" StartPoint="0,0.5" EndPoint="1,0.5" Opacity="0.5">
    <LinearGradientBrush.GradientStops>
      <GradientStopCollection>
        <GradientStop Color="GoldenRod" Offset="0" />
        <GradientStop Color="White" Offset="1" />
      </GradientStopCollection>
    </LinearGradientBrush.GradientStops>
  </LinearGradientBrush>
</StackPanel.Resources>

<!-- Non-shared Brush object. -->
<Label>
  Label 1
  <Label.Background>
    <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5" Opacity="0.5">
      <LinearGradientBrush.GradientStops>
        <GradientStopCollection>
          <GradientStop Color="GoldenRod" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </GradientStopCollection>
      </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
  </Label.Background>
</Label>

<!-- Shared Brush object. -->
<Label Background="{StaticResource myBrush}">Label 2</Label>
<Label Background="{StaticResource myBrush}">Label 3</Label>

可能な場合は静的リソースを使用する

静的リソースでは、既に定義されているリソースへの参照を検索することによって、任意の XAML プロパティ属性の値が提供されます。 そのリソース検索動作は、コンパイル時の検索に類似しています。

一方、動的リソースでは、初期コンパイル中に一時式が作成されます。そのため、オブジェクトを構築するために要求されたリソース値が実際に必要になるまで、リソースの検索が遅延されます。 そのリソース検索動作は、実行時の検索に類似しており、パフォーマンスに影響します。 アプリケーションでは、必要な場合にのみ動的リソースを使用して、可能な限り静的リソースを使用してください。

次のマークアップ サンプルは、両方の種類のリソースの使用方法を示しています。

<StackPanel.Resources>
  <SolidColorBrush x:Key="myBrush" Color="Teal"/>
</StackPanel.Resources>

<!-- StaticResource reference -->
<Label Foreground="{StaticResource myBrush}">Label 1</Label>

<!-- DynamicResource reference -->
<Label Foreground="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">Label 2</Label>

関連項目