2011-08-28 47 views
5

Opracowuję program BlackJack, który pokazuje stół BlackJack, karty itp. Plan polega na tym, że będzie grał tysiące rozdań po kolei za pomocą automatycznej strategii.C# WPF BitmapSource Wyciek pamięci?

Mam PlayerSeat UserControl, który zawiera ItemsControl związany z ObservableCollection. Ta klasa CardInHand zawiera BitmapSource o nazwie CardImage. Gdy instancja jest crated ładuje obraz karty z zasobów za pomocą następującego kodu:

[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; 
} 

Problemem jest to, że po tym, jak prowadzony przez ~ 500 rund (~ 4000 rąk lub ~ 10000 cards) I skończyć z GDI + błąd i aplikacja zajmująca ~ 400 MB pamięci RAM. Rośnie szybko i jest zależna od liczby rozdań, które zostały zagrane.

DeleteObject() to coś, co znalazłem na innej stronie, która mówi, że jest to najlepszy sposób na uwolnienie zasobów z Bitmapy. To może mieć mały wpływ, ale nie to, czego szukam. Próbowałem również Dispose().

Inna strona powiedziała, że ​​miało to związek z powiązaniem ItemsSource. Usunąłem wiązanie i pamięć wciąż rosła. Odwrotnie opuściłem wiązanie i usunąłem kod, który generuje bitmapę. Rozegrało 40 000 rund i nie wzrosło znacząco (może + 20MB w ciągu 40 minut, gdy był uruchomiony).

ObservableCollection jest przezroczysty() ed po każdej rundzie. Próbowałem zerwać kolekcję, CardInHand i propozycję BitmapSource, bezskutecznie.

W jaki sposób mogę zezwolić na wyświetlanie tych obrazów na ekranie, ale także upewnić się, że ich obiekty są niszczone, gdy nie są już potrzebne?

Dziękuję za poświęcony czas.

Odpowiedz

6

Po pierwsze, masz tylko 52 karty. Po prostu twórz obrazy z przodu i trzymaj je przez cały okres użytkowania aplikacji. W końcu jest to gra Black Jack; można bezpiecznie założyć, że każda karta będzie potrzebna w takim czy innym punkcie.

To powiedziawszy, istnieje problem z tworzeniem obiektów BitmapSource ze strumieni. byte[] utrzymywany przez strumień nie jest zwalniany, gdy strumień jest usuwany. See my own question here. Jedynym powodem, dla którego nie głosowałem, aby zamknąć jako duplikat, jest to, że uważam, że powinieneś po prostu stworzyć karty raz i skończyć z tym, zamiast tworzyć te obrazy ponad 10 000 razy.

+0

Ma to sens. Jeśli generuję BitmapSource przy uruchamianiu aplikacji, powinienem móc to odwołać? Po prostu zapisuje odniesienie do oryginalnego BitmapSource w klasie CardInHand, a nie duplikuje danych, prawda? –

+0

51 kart? 52? ... –

+0

.... Geez, tak ... 52. Stojaki na punkty = D –