C# WPF映像中未释放内存
我正在C# WPF映像中未释放内存,c#,wpf,image,canvas,memory-leaks,C#,Wpf,Image,Canvas,Memory Leaks,我正在画布中加载和卸载图像。我使用下面的代码加载图像 在加载我的图像之前内存消耗为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.A
画布中加载和卸载图像。我使用下面的代码加载图像
在加载我的图像之前
内存消耗为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
图像
显示正确,内存消耗现在为20.8MB。然后我用下面的代码卸载了图像
:
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();
此后,图像
将被删除,但内存仍为20.8MB
有人能帮我解决这个问题吗?在.Net中,有一种叫做垃圾收集器(GC)的东西,负责管理您正在使用的内存
- 创建对象实例时,需要更多内存
- 当您从
Children
集合中删除ImageSource
时,实际上并没有释放任何内存,您只需说“我不想再使用此实例”
此时GC将帮助您。它将自动检测不再使用的实例,并为您释放相关内存
请注意,这是一个自动过程,您不应该(也不想)管理内存
您可以调用GC.Collect()
要强制垃圾收集器立即执行其工作,您将看到内存将被释放注意:GC.Collect()代码>应该在调试中用于检测内存泄漏,但99%的时候不应该在生产代码中显式调用它<代码>GC.Collect()
是一种占用大量CPU时间的操作。在.Net中,有一种叫做垃圾收集器(GC)的东西,负责管理您正在使用的内存
- 创建对象实例时,需要更多内存
- 当您从
Children
集合中删除ImageSource
时,实际上并没有释放任何内存,您只需说“我不想再使用此实例”
此时GC将帮助您。它将自动检测不再使用的实例,并为您释放相关内存
请注意,这是一个自动过程,您不应该(也不想)管理内存
您可以调用GC.Collect()
要强制垃圾收集器立即执行其工作,您将看到内存将被释放注意:GC.Collect()代码>应该在调试中用于检测内存泄漏,但99%的时候不应该在生产代码中显式调用它<代码>GC.Collect()
是一个会占用大量CPU时间的操作。首先,您应该通过显式调用GC.Collect()
来收集内存,并查看内存是否释放,因为GC收集是不确定的。您不能确定在方法执行之后GC是否运行并回收内存
所以,在最后,将此代码显式地强制GC运行,以检查是否实际释放了内存:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
但是,BitmapImage
创建中存在一些已知的内存泄漏问题,您可以参考这些问题
实际上,WPF在静态位图图像和图像之间保持了一个强引用,并在位图图像上钩住了一些事件。因此,在分配给图像之前,您应该冻结位图图像。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;
首先,您应该显式调用GC.Collect()
来收集内存,并查看内存是否释放,因为GC收集是不确定的。您不能确定在方法执行之后GC是否运行并回收内存
所以,在最后,将此代码显式地强制GC运行,以检查是否实际释放了内存:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
但是,BitmapImage
创建中存在一些已知的内存泄漏问题,您可以参考这些问题
实际上,WPF在静态位图图像和图像之间保持了一个强引用,并在位图图像上钩住了一些事件。因此,在分配给图像之前,您应该冻结位图图像。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;
你怎么收集垃圾?那不是内存泄漏。GC最终会处理那些不再引用的实例。@ken2k:我不明白你的意思。你能告诉我你是怎么收集垃圾的吗?那不是内存泄漏。GC最终会处理那些不再引用的实例。@ken2k:我不明白你的意思。你能不能请ElLobrate这样我就可以使用图像了,在我的工作完成后,我将imageSource设置为null并调用GC.Collect()。。但记忆不会被清理。。过了一段时间,当我再次调用GC.Collect()时,它的clean else它的hold memory cheak video:-所以我使用图像,在我的工作完成后,我将imageSource设置为null并调用GC.Collect()。。但记忆不会被清理。。过了一段时间,当我再次调用GC.Collect()时,它的clean else将保留内存cheak视频:-