内存未在WPF映像中发布

Uth*_*aj. 1 c# wpf memory-leaks canvas image

我正在加载和卸载图像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
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

Image这之后被删除,但仍然记忆是20.8 MB.

任何人都可以帮助我吗?

Roh*_*ats 9

首先,您应该通过显式调用GC.Collect()来收集内存并查看内存是否发布,因为GC集合是不确定的.在方法执行GC运行并回收内存后,您无法确定.

因此,最后将此代码显式强制GC运行以检查实际内存是否已释放:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Run Code Online (Sandbox Code Playgroud)

但是,创建中存在一些已知的内存泄漏问题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;
Run Code Online (Sandbox Code Playgroud)