我的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();
}
在循环中,我们加载50次相同的图片(逐个)。它模拟用户可以更改图片的场景。它应该替换前一个,然后重新加载下一个。我不明白为什么它在4次迭代后失败了。如果第一次和第二次有足够的内存加载它,为什么以后没有足够的重新加载它?
这是我加载图片的方式:
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());
}
经过几次迭代后失败(DecodedFailed)(它会崩溃,只会引发事件)。例外是:
System.OutOfMemoryException:内存不足,无法继续执行程序。 在System.Windows.Media.Imaging.BitmapSource.CreateCachedBitmap(BitmapFrame框架,BitmapSourceSafeMILHandle wicSource,BitmapCreateOptions createOptions,BitmapCacheOption cacheOption,BitmapPalette调色板) 在System.Windows.Media.Imaging.CachedBitmap.FinalizeCreation() 在System.Windows.Media.Imaging.CachedBitmap.EndInit() 在System.Windows.Media.Imaging.CachedBitmap..ctor(BitmapSource源,BitmapCreateOptions createOptions,BitmapCacheOption cacheOption) 在System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
我尝试了不同的东西: - 改变缓存模式 - 处理流。 - 冻结 - 如果我没有附加任何事件也会发生(我知道BitmapImage的事件有众所周知的内存泄漏)
请注意,没有任何约束。我在画布上画了一张照片就是这样。我使用http://followhislight.files.wordpress.com/2013/08/map_of_the_world_1998.jpg测试了代码。
经过4次迭代后并不总是如此。这一切都取决于可用的内存和图片大小。