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.
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? –
51 cartas? 52? ... –
.... Caray, sí ... 52. Point stands = D –