我正在对Silverlight OOB应用程序中的某些图像执行一组操作,但是在针对多个较大图像执行这些操作时遇到OutOfMemoryExceptions。图像本身大约是15mb的JPEG文件,当加载到BitmapImage中时,它们单独使用大约100mb的内存。
我正在逐个处理这些图像,但是BitmapImage本身并没有在图像之间进行清理。处理10个图像时,内存使用量(如任务管理器中所示)增长到一个大小的gig,然后在完成该过程后折回到100mb。
我已将问题提炼到浏览器测试应用程序中,该应用程序只是将图像数据加载到BitmapImage对象中,并包含以下代码:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
byte[] imageData = LoadImageData();
for (int i = 0; i < 10; i++)
{
BitmapImage bitmapImage = new BitmapImage();
using (MemoryStream memoryStream = new MemoryStream(imageData))
{
bitmapImage.SetSource(memoryStream);
}
GC.Collect();
}
}
private byte[] LoadImageData()
{
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ImageLoadingMemoryIssue.largeimage.jpg"))
{
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
return buffer;
}
}
如何在循环内的每次迭代之间强制清除BitmapImage
以防止在处理多个文件时出现内存问题?
由于
答案 0 :(得分:0)
for (int i = 0; i < 10; i++)
{
BitmapImage bitmapImage = new BitmapImage();
using (MemoryStream memoryStream = new MemoryStream(imageData))
{
bitmapImage.SetSource(memoryStream);
}
// release reference underlying byte array
// see: http://code.logos.com/blog/2008/04/memory_leak_with_bitmapimage_and_memorystream.html
bitmapImage.SetSource(null);
GC.Collect();
}
答案 1 :(得分:0)
我设法通过等待ImageOpened / Failed事件来解决这个问题,然后继续并加载和处理下一个图像。由于某种原因,这允许在那时清除内存,而不是等待加载所有图像。
private static async Task<BitmapImage> LoadBitmapImageAsync(byte[] imageData)
{
BitmapImage bi = new BitmapImage();
TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>();
EventHandler<RoutedEventArgs> openedHandler = (s2, e2) => taskCompletionSource.TrySetResult(null);
EventHandler<ExceptionRoutedEventArgs> failedHandler = (s2, e2) => taskCompletionSource.TrySetResult(null);
bi.ImageOpened += openedHandler;
bi.ImageFailed += failedHandler;
using (MemoryStream memoryStream = new MemoryStream(imageData))
{
bi.SetSource(memoryStream);
}
await taskCompletionSource.Task;
bi.ImageOpened -= openedHandler;
bi.ImageFailed -= failedHandler;
return bi;
}