C# 如何在Silverlight中强制清理BitmapImage
我正在对Silverlight OOB应用程序中的一些图像执行一组操作,但是在对多个较大的图像执行这些操作时,我遇到OutOfMemoryException。这些图像本身是大约15mb的JPEG文件,当加载到BitmapImage中时,它们各自会占用大约100mb的内存 我正在一个接一个地处理这些图像,但是位图图像本身并没有在图像之间被清理。当处理10个图像时,内存使用量(如任务管理器中所示)会增长到超过1千兆字节,然后在处理完成后会收缩回100mb 我将问题归结为一个浏览器内测试应用程序,该应用程序只需将图像数据加载到BitmapImage对象中,并由以下代码组成:C# 如何在Silverlight中强制清理BitmapImage,c#,silverlight,C#,Silverlight,我正在对Silverlight OOB应用程序中的一些图像执行一组操作,但是在对多个较大的图像执行这些操作时,我遇到OutOfMemoryException。这些图像本身是大约15mb的JPEG文件,当加载到BitmapImage中时,它们各自会占用大约100mb的内存 我正在一个接一个地处理这些图像,但是位图图像本身并没有在图像之间被清理。当处理10个图像时,内存使用量(如任务管理器中所示)会增长到超过1千兆字节,然后在处理完成后会收缩回100mb 我将问题归结为一个浏览器内测试应用程序,该应
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;
}
}
private void按钮base\u OnClick(对象发送方,路由目标)
{
字节[]imageData=LoadImageData();
对于(int i=0;i<10;i++)
{
BitmapImage BitmapImage=新的BitmapImage();
使用(MemoryStream MemoryStream=新的MemoryStream(imageData))
{
bitmapImage.SetSource(memoryStream);
}
GC.Collect();
}
}
专用字节[]LoadImageData()
{
使用(var stream=Assembly.getExecutionGassembly().GetManifestResourceStream(“ImageLoadingMemorySue.largeimage.jpg”))
{
byte[]buffer=新字节[stream.Length];
stream.Read(buffer,0,buffer.Length);
返回缓冲区;
}
}
如何在循环中的每次迭代之间强制清理位图图像
,以防止处理多个文件时出现内存问题
感谢(inti=0;i<10;i++)
{
BitmapImage BitmapImage=新的BitmapImage();
使用(MemoryStream MemoryStream=新的MemoryStream(imageData))
{
bitmapImage.SetSource(memoryStream);
}
//释放引用底层字节数组
//见:http://code.logos.com/blog/2008/04/memory_leak_with_bitmapimage_and_memorystream.html
bitmapImage.SetSource(空);
GC.Collect();
}
我通过等待ImageOpen/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;
}
专用静态异步任务LoadBitmapImageAsync(字节[]imageData)
{
BitmapImage bi=新的BitmapImage();
TaskCompletionSource TaskCompletionSource=新的TaskCompletionSource();
EventHandler openedHandler=(s2,e2)=>taskCompletionSource.TrySetResult(null);
EventHandler failedHandler=(s2,e2)=>taskCompletionSource.TrySetResult(null);
bi.ImageOpened+=openedHandler;
bi.ImageFailed+=failedHandler;
使用(MemoryStream MemoryStream=新的MemoryStream(imageData))
{
bi.SetSource(内存流);
}
等待taskCompletionSource.Task;
bi.ImageOpened-=openedHandler;
bi.ImageFailed-=failedHandler;
返回bi;
}
您是否尝试过保留一个全局变量并设置其源代码?这没有什么区别,内存使用没有得到清理。我还尝试将源设置为一个小图像,以强制它清理-这里有一些东西没有正确清理。一旦退出循环,它最终会消失,因此它不是传统意义上的内存泄漏。如果是这种情况,您是否尝试将for循环的内容放入方法中?我对Silverlight了解不多,但是你能用类似的东西来分析你的应用程序吗?这是我以前尝试过的事情之一,除了SetSource(null)
抛出异常之外,它不会导致释放内存使用,虽然我现在已经找到了一种方法来实现它,但我也尝试了链接文章中提到的包流方法。我认为这篇文章更多的是关于WPF的,因为我没有看到所描述的内存问题。
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;
}