内存未在WPF映像中发布
我在Canvas
加载和卸载图像。 我使用下面的代码加载Image
。
在加载我的Image
之前,内存消耗为14.8MB。
Canvas c = new Canvas(); Image im = new Image(); ImageSource src = new BitmapImage(new Uri(@"E:Capture.png")); im.Source = src; im.Height = 800; im.Width = 800; c.Children.Add(im); homegrid.Children.Add(c); //homegrid is my grid's name
Image
显示正确,内存消耗现在为20.8MB。 然后我通过以下代码卸载了Image
:
foreach (UIElement element in homegrid.Children) { if (element is Canvas) { Canvas page = element as Canvas; if (page.Children.Count > 0) { for (int i = page.Children.Count - 1; i >= 0; i--) { if (page.Children[i] is Image) (page.Children[i] as Image).Source = null; page.Children.RemoveAt(i); } } page.Children.Clear(); page = null; } } homegrid.Children.RemoveAt(2); InvalidateVisual();
此后Image
被删除,但内存仍为20.8 MB。
任何人都可以帮助我吗?
首先,您应该通过显式调用GC.Collect()
来测试以收集内存并查看内存是否发布,因为GC集合是不确定的。 在方法执行GC运行并回收内存后,您无法确定。
因此,最后将此代码显式强制GC运行以检查实际内存是否已释放:
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
但是,在BitmapImage
创建中存在一些已知的内存泄漏问题,您可以在这里 , 此处和此处引用。
实际上,WPF在静态BitmapImage和Image之间保留了强大的参考,并在Bitmap图像上挂了一些事件。 因此,您应该在分配给图像之前冻结bitmapImage 。 WPF不会在冻结的bitmapImage上挂钩事件。 还要设置CacheOption以避免bitmapImage的任何缓存内存泄漏。
Image im = new Image(); BitmapImage bi = new BitmapImage(); bi.BeginInit(); bi.CacheOption = BitmapCacheOption.OnLoad; bi.UriSource = new Uri(@"E:Capture.png"); bi.EndInit(); bi.Freeze(); ImageSource src = bi; im.Source = src; im.Height = 800; im.Width = 800;
在.Net中有一种称为垃圾收集器 (GC)的东西负责管理你正在使用的内存。
- 创建对象的实例时,需要更多内存。
- 当您从
Children
集合中删除ImageSource
,实际上并没有释放任何内存,只需说“ 我不想再使用此实例 ”。
此时GC将帮助您。 它会自动检测不再使用的实例,并为您释放相关的内存。
请注意,这是一个自动过程 ,您不应该(并且您不想)负责内存管理。
你可以调用GC.Collect();
要强制垃圾收集器立即完成其工作,您将看到内存将被释放。 注意: GC.Collect();
应该在调试中用于检测内存泄漏,但99%的时候你不应该在生产代码中明确地调用它 。 GC.Collect();
是一种可以占用大量CPU时间的操作。