2011-08-28 27 views
5

Estoy desarrollando un programa BlackJack que muestra una BlackJack Table, cartas, etc. El plan es que jugará miles de manos una tras otra con una estrategia automatizada.C# WPF BitmapSource ¿Fuga de memoria?

Tengo un UserControl PlayerSeat que contiene un ItemsControl vinculado a un ObservableCollection. Esta clase CardInHand contiene un BitmapSource llamado CardImage. Cuando se embaló la instancia se carga la imagen de tarjeta de recursos utilizando el siguiente código:

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

El problema es que después de ejecutar a través de ~ 500 rondas (~ 4000 de manos o ~ 10000 tarjetas) que terminan con un GDI + error y la aplicación que toma ~ 400MB de RAM. Esto crece rápidamente y está relacionado con la cantidad de manos que se han jugado.

DeleteObject() es algo que he encontrado en otro sitio que dice que esta es la mejor manera de liberar los recursos del mapa de bits. Es posible que tenga un pequeño efecto, pero no es lo que estoy buscando. También intenté Dispose().

Otro sitio dijo que tenía que ver con el enlace ItemsSource. Eliminé el enlace y la memoria aún creció. Inversamente, dejé el enlace y eliminé el código que genera el mapa de bits. Jugó 40,000 rondas y no creció sustancialmente (tal vez + 20MB durante los 40min que estaba corriendo).

ObservableCollection se borra() ed después de cada ronda. Intenté anular la colección, CardInHand y la propiedad de BitmapSource, sin éxito.

¿Cómo puedo permitir que estas imágenes se muestren en la pantalla, pero también me aseguro de que sus objetos se destruyan correctamente después de que ya no se necesiten?

Gracias por su tiempo.

Respuesta

6

Primero, solo tienes 52 cartas. Solo crea las imágenes por adelantado y mantenlas durante la vida de la aplicación. Es un juego de Black Jack después de todo; es seguro suponer que cada tarjeta será necesaria en un punto u otro.

Dicho esto, hay un problema con la creación de objetos BitmapSource de las secuencias. El byte[] retenido por la transmisión no se libera cuando se elimina la transmisión. See my own question here. La única razón por la que no voté para cerrar como duplicado es porque creo que realmente deberías crear las cartas una vez y terminar con ellas en lugar de crear estas imágenes más de 10.000 veces.

+0

Esto tiene sentido. Si genero un BitmapSource en el inicio de la aplicación, ¿podría simplemente hacer referencia a eso? Simplemente almacenará una referencia al BitmapSource original en la clase CardInHand, y no duplicará los datos, ¿verdad? –

+0

51 cartas? 52? ... –

+0

.... Caray, sí ... 52. Point stands = D –