C# WPF,在循环中加载图像(BitmapImage)

C# WPF,在循环中加载图像(BitmapImage),c#,wpf,memory,memory-leaks,bitmapimage,C#,Wpf,Memory,Memory Leaks,Bitmapimage,我对BitmapImage类有问题。我知道有几个类似的问题,但我找不到这个问题的答案 基本上,当我加载几次大图片时,它会抛出无声异常。我试图创建一个简单的应用程序来解决这个问题 实际情况当然不同,这只是为了重现。比如说,在按钮点击事件中,我们有: var openFileDialog=new OpenFileDialog(); if (openFileDialog.ShowDialog()==true) { BitmapI

我对BitmapImage类有问题。我知道有几个类似的问题,但我找不到这个问题的答案

基本上,当我加载几次大图片时,它会抛出无声异常。我试图创建一个简单的应用程序来解决这个问题

实际情况当然不同,这只是为了重现。比如说,在按钮点击事件中,我们有:

        var openFileDialog=new OpenFileDialog();

        if (openFileDialog.ShowDialog()==true)
        {
            BitmapImage bitmapImage = null;

            for (int i = 0; i < 50; i++)
            {
                if (bitmapImage != null)
                {
                    bitmapImage.StreamSource.Dispose();
                    bitmapImage.DecodeFailed -= bitmap_DecodeFailed;
                    canvas.Bitmap = null;


                }

                bitmapImage = Load(openFileDialog.FileName);
                Thread.Sleep(100);                                    
                Debug.WriteLine(GC.GetTotalMemory(false));
            }

            canvas.Bitmap = bitmapImage;
            canvas.InvalidateVisual();
        }
它在几次迭代后失败(DecodedFailed)(它没有崩溃,只是引发了事件)。例外情况是:

System.OutOfMemoryException:内存不足,无法继续执行程序。 位于System.Windows.Media.Imaging.BitmapSource.CreateCachedBitmap(BitmapFrame框架、BitmapSourceSafeMILHandle wicSource、BitmapCreateOptions createOptions、BitmapCacheOption缓存选项、BitmapPalette调色板) 在System.Windows.Media.Imaging.CachedBitmap.FinalizeCreation()中 在System.Windows.Media.Imaging.CachedBitmap.EndInit()中 位于System.Windows.Media.Imaging.CachedBitmap..ctor(BitmapSource源、BitmapCreateOptions createOptions、BitmapCacheOption缓存选项) 位于System.Windows.Media.Imaging.BitmapImage.FinalizeRecreation()处

我尝试了不同的方法: -更改缓存模式 -处理流。 -冻结 -如果我没有附加任何事件,也会发生这种情况(我知道BitmapImage的事件存在众所周知的内存泄漏)

请注意,没有任何绑定。我在画布上画了一幅画,就这样。我使用测试工具测试了代码


并不总是在4次迭代之后。这一切都取决于可用内存和图片大小。

如果在调用
Load
之前通过调用
GC.Collect()
在每个循环周期中强制垃圾收集,它将如何工作?在许多情况下(并非总是),强制收集工作-可用内存是恒定的。然而,我不想强制GC,当内存不足时,收集应该自动启动。
    public BitmapImage Load(string path)
    {
        var memoryStream = new MemoryStream();

        using (var reader = new BinaryReader(File.Open(path, FileMode.Open)))
        {
            byte[] allData = reader.ReadBytes((int) reader.BaseStream.Length);
            memoryStream.Write(allData, 0, allData.Length);
        }

        memoryStream.Position = 0;


        var bitmap = new BitmapImage();
        bitmap.DecodeFailed += bitmap_DecodeFailed;

        bitmap.BeginInit();
        bitmap.StreamSource = memoryStream;
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.EndInit();

        return bitmap;

    }

    void bitmap_DecodeFailed(object sender, ExceptionEventArgs e)
    {
        MessageBox.Show(e.ErrorException.ToString());
        Environment.FailFast(e.ErrorException.ToString());
    }