我正在开发一个BlackJack程序,显示BlackJack表,卡片等。计划是通过自动化策略一个接一个地玩数千手。
我有一个PlayerSeat UserControl,它包含一个绑定到ObservableCollection的ItemsControl。此CardInHand类包含名为CardImage的BitmapSource。当实例被装箱时,它使用以下代码从资源加载卡片图像:
[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 +错误,应用程序占用了大约400MB的RAM。这种情况会迅速增长,并且与已经玩过的牌数有关。
DeleteObject()是我在另一个网站上发现的,它说这是从Bitmap释放资源的最佳方式。这可能会产生一些影响,但不是我正在寻找的东西。我也试过Dispose()。
另一个网站表示它与ItemsSource绑定有关。我删除了绑定,内存仍然增长。反过来,我离开了绑定并删除了生成位图的代码。它打了4万发子弹并没有大幅度增长(在运行的40分钟内可能+ 20MB)。
每一轮后,ObservableCollection为Clear()。我已经尝试将集合,CardInHand和BitmapSource属性归零,但无济于事。
如何让这些图像显示在屏幕上,同时确保它们的对象在不再需要后会被破坏?
感谢您的时间。
答案 0 :(得分:6)
首先,你只有52张牌。只需预先创建图像并在应用程序的生命周期中保留它们。毕竟这是一个黑杰克游戏;可以安全地假设每张卡都需要在某一点或另一点。
也就是说,从流中创建BitmapSource
对象存在问题。处理流时,流不会释放流所持有的byte[]
。 See my own question here。我没有投票以关闭作为副本的唯一原因是因为我认为你应该只创建一次卡片并完成它而不是创建这些图像10,000次以上。