Подтвердить что ты не робот

В каких сценариях замораживание объектов WPF значительно повышает производительность?

Многие типы в WPF получают Freezable. Он обеспечивает неизменность изменчивых объектов POCO и, по-видимому, позволяет улучшить производительность в определенных ситуациях.

Кто-нибудь нашел, что замораживание объектов в их приложении WPF значительно улучшило производительность? Если это так, то какие элементы дали наибольшую разницу в производительности при замораживании?

(Обратите внимание, что я разместил аналогичный, но другой вопрос)

4b9b3361

Ответ 1

Вам может быть интересен мой опыт работы с Freezable:

Я однажды написал программу просмотра PDF, используя muPdf, который отображает растровые изображения, которые я визуализирую с помощью WPF. Что значительно повышает производительность, так это то, что я могу отображать растровые изображения на фоновом потоке, замораживать их и передавать их в поток пользовательского интерфейса. Приятно, что WPF не копирует изображение, чтобы заморозить его, но возможность сделать все это в фоновом потоке была для меня ключевым преимуществом.

Из того, что я понимаю, все визуальные эффекты необходимо заморозить, чтобы их можно было безопасно отображать в потоке рендеринга WPF. Если вы визуализируете большие незамерзшие визуальные эффекты, они будут клонированы к замороженным, когда WPF отобразит их. Если вы предварительно заморозили свои статические растровые изображения, WPF может просто поделиться указателем с потоком рендеринга без клонирования. Незамерзшие объекты могут даже многократно копироваться, если WPF не знает, изменяется ли объект с момента последнего его рендеринга. Замороженные объекты устраняют необходимость во всем этом копировании.

Ответ 2

Эти потенциальные утечки памяти могут произойти, если вы используете элемент управления 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

Ответ 3

Хотя вы уже приняли ответ, просто захотелось записать другую версию ответа, которая помогла мне лучше.

Из MSDN (незначительное редактирование):

Если вы хотите изменить ссылку на контрольный холдинг для неуправляемых ресурсов низкого уровня (например, Brush), каждая модификация должна была бы восстановить те объекты низкого уровня!

Свободный класс - это то, что дает кисти способность найти соответствующие сгенерированные объекты низкого уровня и обновить когда они меняются. Когда эта способность включена, кисть называется быть "размороженными".

Свободный метод 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;
            }

Ответ 4

Я разработал высокопроизводительное приложение для просмотра изображений. У нас был код на внутреннем контенте, который создал новый растровый образ каждого кадра и написал это растровое изображение на экран следующим образом:

Writeablebitmap wb = new WriteableBitmap();
//  < code to set the wb pixel values here >

// Push the bitmap to the screen
image.Source = wb;

Во время тестирования мы заметили, что произошло ужасное мерцание при движении 30+ FPS с изображениями умеренного размера (1080p). Исправить? Просто заморозите растровое изображение, прежде чем устанавливать его на изображение. Источник. Больше не ошибка производительности продукта. В настоящее время я пытаюсь заморозить все, что могу.