WPF の多くの型は から派生していFreezable
ます。変更可能な POCO オブジェクトに不変性を提供し、明らかに、特定の状況でパフォーマンスを向上させることができます。
WPF アプリケーション内でオブジェクトをフリーズすると、パフォーマンスが大幅に向上することに気付いた人はいますか? もしそうなら、凍結されたときに最大のパフォーマンスの違いをもたらしたのはどのアイテムですか?
(同様の別の質問も投稿したことに注意してください)
WPF の多くの型は から派生していFreezable
ます。変更可能な POCO オブジェクトに不変性を提供し、明らかに、特定の状況でパフォーマンスを向上させることができます。
WPF アプリケーション内でオブジェクトをフリーズすると、パフォーマンスが大幅に向上することに気付いた人はいますか? もしそうなら、凍結されたときに最大のパフォーマンスの違いをもたらしたのはどのアイテムですか?
(同様の別の質問も投稿したことに注意してください)
Freezable に関する私の経験に興味があるかもしれません。
私はかつて、ビットマップをレンダリングする muPdf を使用して PDF ビューアーを作成し、それを WPF でレンダリングしました。パフォーマンスを大幅に向上させるのは、ページのビットマップをバックグラウンド スレッドでレンダリングし、フリーズしてから UI スレッドに渡すことができることです。WPF がイメージをコピーしてフリーズしないのは良いことですが、このすべての準備をバックグラウンド スレッドで実行できることは、私にとって重要な利点でした。
私が理解していることから、すべてのビジュアルを凍結して、WPF レンダリング スレッドで安全にレンダリングできるようにする必要があります。凍結されていない大きなビジュアルをレンダリングすると、WPF がレンダリングするときに凍結されたビジュアルに複製されます。事前に静的ビットマップをフリーズすると、WPF はクローンを作成せずにポインターをレンダリング スレッドと共有できます。オブジェクトが最後にレンダリングされてから変更されたかどうかを WPF が認識していない場合、凍結されていないオブジェクトが繰り返しコピーされることさえあります。オブジェクトを凍結すると、このすべてのコピーの必要がなくなります。
Image コントロールを使用する場合 (かつ Freeze メソッドを使用しない場合)、次の潜在的なメモリ リークが発生する可能性があります。
a) BitmapImage を画像ソースとして使用し、BitmapImage を解放しない:
static BitmapImage bi1 = new BitmapImage(new Uri("Bitmap1.bmp",UriKind.RelativeOrAbsolute));
m_Image1 = new Image();
m_Image1.Source = bi1;
//bi1.Freeze()
//if you do not Freeze, your app will leak memory.
MyStackPanel.Children.Add(m_Image1);
b) 複数の BitmapImage をイメージ ソースとして割り当て、使用した BitmapImage のすべてを解放しない ((a) と同様)。これは.Net 3.5で導入されました:
static BitmapImage bi1 = new BitmapImage(new Uri("Bitmap1.bmp",
UriKind.RelativeOrAbsolute));
static BitmapImage bi2 = new BitmapImage(new Uri("Bitmap2.bmp",
UriKind.RelativeOrAbsolute));
bi2.Freeze();
m_Image1 = new Image();
//bi1.Freeze()
//even though you are really using bi2 for Image Source,
//you also need to Freeze bi1 it to avoid leak
m_Image1.Source = bi1; // use un-frozen bitmap, which causes the leak
m_Image1.Source = bi2; // use frozen bitmap
MyStackPanel.Children.Add(m_Image1);
出典: WPF パフォーマンス
あなたはすでに答えを受け入れていますが、私を助けてくれた別のバージョンの答えを記録したかっただけです。
MSDNから(マイナー編集):
管理されていない低レベル リソース (例: ブラシ) への参照を保持するコントロールを変更する場合、すべての変更でそれらの低レベル オブジェクトを再生成する必要があります。
freezable クラスは、対応する生成された低レベル オブジェクトを見つけて、変更されたときにそれらを更新する機能をブラシに与えるものです。この機能を有効にすると、ブラシは「凍結解除」されたと言われます。
freezable の Freeze メソッドを使用すると、この自己更新機能を無効にすることができます。このメソッドを使用して、ブラシを「固定」または変更不可にすることができます。したがって、パフォーマンスが向上します。
そして、使用法を説明するコード:
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
myButton.Background = myBrush;
if (myBrush.IsFrozen) // Evaluates to true.
{
// If the brush is frozen, create a clone and modify the clone.
SolidColorBrush myBrushClone = myBrush.Clone();
myBrushClone.Color = Colors.Red;
myButton.Background = myBrushClone;
}
else
{
// If the brush is not frozen, it can be modified directly.
myBrush.Color = Colors.Red;
}
高機能な画像ビューアアプリを開発しました。フレームごとに新しいビットマップを作成し、そのビットマップを次のように画面に書き込むコードがバックエンドにありました。
Writeablebitmap wb = new WriteableBitmap();
// < code to set the wb pixel values here >
// Push the bitmap to the screen
image.Source = wb;
テスト中に、中程度のサイズの画像 (1080p) で 30+ FPS を使用しているときにひどいちらつきがあることに気付きました。修正?image.Source に設定する前に、ビットマップをフリーズするだけです。製品を破壊するパフォーマンス バグはもうありません。現在、私はできる限りすべてを凍結しようとしています。