Удалить изображение в WPF в Listbox (утечка памяти)

У меня есть ListBox с кучей изображений (сделано через datatemplate). Изображения создаются путем установки источника элементов:

<Image x:Name = "ItemImage" Source = "{Binding ImageUrl}"/> 

а затем они очищаются с помощью метода Items.Clear () списка. Новые изображения добавляются с помощью метода Items.Add списка.

Однако использование памяти только начинает расти и расти. Отображаются те же 300 или около того маленьких изображений, но память, кажется, никогда не освобождается. Приложение начинает использовать около 40 мегабайт и быстро достигает 700 мегабайт. Как мне освободить память, которую используют все эти изображения?

РЕДАКТИРОВАТЬ: Одна вещь, которую я забыл упомянуть, изображения (размером около 4-5k каждое) загружаются по сети. Кеширование как-то отвечает за это? Отображение 12 изображений занимает около 10 мегабайт памяти, что примерно в 100 раз превышает размер файла.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
6 649
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы не делаете ничего необычного при загрузке изображений (например, используете самодельные загрузчики изображений или что-то в этом роде), тогда GC должен стереть их за вас, когда на них больше ничего не ссылается.

Вы где-нибудь держитесь ссылок на данные? Помните, что события и обработчики событий могут иногда «обмануть» сборщика мусора, заставив его думать, что объект все еще используется:

MyObject obj = new MyObject();
obj.TheEvent += new EventHandler(MyHandler);
obj = null;
// Now you might think that obj is set for collection but it 
// (probably - I don't have access to MS' .NET source code) isn't 
// since we're still listening to events from it.

Не уверен, что это относится к вам, но, по крайней мере, я бы проверил, был ли я вами.

Кроме того, если у вас есть доступ к профилировщику, например AQTime или аналогичному, то запуск вашего кода через него может дать вам некоторые подсказки.

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

Как насчет того, чтобы вообще не использовать всю эту память?

(Примечание: Следующий абзац и код воспроизводятся из этот ответ.)

Part of the problem is that it is loading the full image in each. You have to use an IValueConverter to open each image in a thumbnail size by setting either the DecodePixelWidth or DecodePixelHeight properties on the BitmapImage. Here's an example I use in one of my projects...

class PathToThumbnailConverter : IValueConverter {
    public int DecodeWidth {
        get;
        set;
    }

    public PathToThumbnailConverter() {
        DecodeWidth = 200;
    }

    public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
        var path = value as string;

        if ( !string.IsNullOrEmpty( path ) ) {

            FileInfo info = new FileInfo( path );

            if ( info.Exists && info.Length > 0 ) {
                BitmapImage bi = new BitmapImage();

                bi.BeginInit();
                bi.DecodePixelWidth = DecodeWidth;
                bi.CacheOption = BitmapCacheOption.OnLoad;
                bi.UriSource = new Uri( info.FullName );
                bi.EndInit();

                return bi;
            }
        }

        return null;
    }

    public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
        throw new NotImplementedException();
    }

}

Вы также можете рассмотреть IsAsync=True в вашем Binding, чтобы преобразователь вызывался в фоновом потоке.

Или даже лучше - используйте встроенный эскиз, если он существует, поэтому вам даже не нужно читать весь файл и изменять его размер ... Поиск BitmapFrame.Thumbnail

Filip Skakun 22.03.2010 23:59

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

Filip Skakun 23.03.2010 19:44

Таким и таким образом браузер может контролировать размер миниатюр.

Joel B Fant 23.03.2010 23:36

Другие вопросы по теме