C # WPF BitmapSource Утечка памяти? - PullRequest
5 голосов
/ 28 августа 2011

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

У меня есть PlayerSeat UserControl, который содержит ItemsControl, связанный с ObservableCollection. Этот класс CardInHand содержит BitmapSource с именем CardImage. Когда экземпляр создается, он загружает образ карты из ресурсов, используя следующий код:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

private BitmapSource GenerateCardImage() {
        Stream TempStream = this.GetType().Assembly.GetManifestResourceStream("BlackJack.Resources.CardImages.Card_" + m_Card.ShortTitle + ".gif");
        System.Drawing.Bitmap sourceBMP = new System.Drawing.Bitmap(TempStream);
        BitmapSource tempBitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            sourceBMP.GetHbitmap(),
            IntPtr.Zero,
            System.Windows.Int32Rect.Empty,
            BitmapSizeOptions.FromWidthAndHeight(sourceBMP.Width, sourceBMP.Height)
        );
        TempStream.Dispose();
        DeleteObject(sourceBMP.GetHbitmap());
        return tempBitmapSource;
}

Проблема в том, что после прохождения ~ 500 раундов (~ 4000 раздач или ~ 10000 карт) у меня возникает ошибка GDI +, и приложение занимает ~ 400 МБ ОЗУ. Это быстро растет и связано с количеством сыгранных рук.

DeleteObject () - это то, что я нашел на другом сайте, который сказал, что это лучший способ освободить ресурсы из растрового изображения. Это МОЖЕТ иметь небольшой эффект, но не то, что я ищу. Я также пробовал Dispose ().

Другой сайт сказал, что это связано с привязкой ItemsSource. Я снял привязку, и память все еще росла. Обратно я оставил привязку и удалил код, который генерирует растровое изображение. Он сыграл 40 000 раундов и существенно не вырос (возможно, + 20 МБ за 40 минут работы).

ObservableCollection очищается () редактируется после каждого раунда. Я попытался обнулить коллекцию, CardInHand и свойство BitmapSource, но безрезультатно.

Как я могу разрешить этим изображениям отображаться на экране, а также убедиться, что их объекты должным образом уничтожены после того, как они больше не нужны?

Спасибо, что уделили время.

1 Ответ

6 голосов
/ 28 августа 2011

Итак, во-первых, у вас есть только 52 карты.Просто создайте изображения заранее и храните их в течение всей жизни приложения.В конце концов, это игра Блэк Джек;Можно с уверенностью предположить, что каждая карта будет нужна в тот или иной момент.

Тем не менее, существует проблема с созданием BitmapSource объектов из потоков.byte[], удерживаемый потоком, не освобождается, когда поток удаляется. См. Мой собственный вопрос здесь .Единственная причина, по которой я не проголосовал за закрытие как дубликат, заключается в том, что я думаю, что вам действительно нужно просто создать карточки один раз и покончить с ними, а не создавать эти изображения более 10000 раз.

...