Windows Phone 8中BitmapImage / Image控件的内存消耗

我正在测试一个WP8应用程序和它的图像查看器来显示许多图像,我发现应用程序的内存消耗正在提高,并希望找到如何解决它。

我已经从网上阅读了一些文章,但这些文章提供的解决方案无法在我的应用上运行,请阅读下面的历史记录。

首先,我找到了文章“ Windows Phone 7的图像提示 ”并下载了它的样本来进行清洁图像缓存测试,它正在使用1个图像

然后出于测试目的,我在应用程序内部使用15个离线图像编译此应用程序,并设置为“内容”,请从此处下载测试应用程序。

我的测试步骤是:

(1) Launch app (2) Go to Image Caching page (3) Enable checkbox "Avoid Image Caching" (4) Continuously tapping button Show/Clear (5) Keep watching the memory status textblock at the bottom 

当我测试我的应用程序时,内存正在提升,如16.02MB =>显示(19.32MB)=>清除( 16.15MB )=>显示(20.18MB)=>清除( 17.03MB )…等内存即使离开缓存页面也不会被释放并再次进入缓存页面。 似乎文章“ Windows Phone 7的图像提示 ”的解决方案仅适用于1个图像

这是“ Windows Phone 7的图像提示 ”解决方案的xaml和代码隐藏。

[Caching.xaml]

          

[Caching.xaml.cs]

 public partial class Caching : PhoneApplicationPage { public Caching() { InitializeComponent(); DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromMilliseconds(500); timer.Start(); timer.Tick += delegate { GC.Collect(); tbMemory.Text = string.Format("Memory: {0} bytes", DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage")); }; } private int nIndex = 1; BitmapImage bitmapImageFromUri = new BitmapImage(); private void ShowImageClicked(object sender, RoutedEventArgs e) { string strImage = string.Format("../ImagesAsContent/{0:D2}.jpg", nIndex); bitmapImageFromUri.UriSource = new Uri(strImage, UriKind.Relative); img.Source = bitmapImageFromUri; nIndex++; if (nIndex > 15) { nIndex = 1; } (sender as ToggleButton).Content = "Clear"; } private void ClearImageClicked(object sender, RoutedEventArgs e) { if (cbAvoidCache.IsChecked == true) { // set the UriSource to null in order to delete the image cache BitmapImage bitmapImageFromUri = img.Source as BitmapImage; bitmapImageFromUri.UriSource = null; } img.Source = null; (sender as ToggleButton).Content = "Show"; } } 

我也尝试搜索任何其他解决方案,一些测试结果如下。

(1)文章“ [wpdev] BitmapImage内存泄漏 ”:它提供了2个解决方案,一个是DisposeImage API,另一个是将BitmapImage源设置为null,如下所示。 另外文章让我们知道我们必须小心事件处理程序附加/分离,但是我的测试应用程序在缓存页面中没有事件处理程序。

[DisposeImage]

 private void DisposeImage(BitmapImage image) { if (image != null) { try { using (var ms = new MemoryStream(new byte[] { 0x0 })) { image.SetSource(ms); } } catch (Exception) { } } } 

[设为空]

 BitmapImage bitmapImage = image.Source as BitmapImage; bitmapImage.UriSource = null; image.Source = null; 

(2)文章“ Windows phone:带有图像内存不足的列表框 ”:它提供了一个API“DisposeImage”,与下面的(1)相比差别不大,但是这也行不通,我还是得到了记忆提高症状。

 public static void DisposeImage(BitmapImage image) { Uri uri= new Uri("oneXone.png", UriKind.Relative); StreamResourceInfo sr=Application.GetResourceStream(uri); try { using (Stream stream=sr.Stream) { image.DecodePixelWidth=1; //This is essential! image.SetSource(stream); } } catch {} } 

(3)文章“ 找不到内存泄漏 ”:它提供了与上述相同的2个解决方案,也提到了对隔离存储的图像无法重现的问题,但是我的测试应用程序的图像来自隔离存储。

(4)我还尝试了1000张图片,当应用程序依次显示大约190张图片时,测试结果是app崩溃,请参考下面的Windows Phone应用程序分析图形获取内存。 在此处输入图像描述

最后,感谢您耐心阅读我的问题和历史,我一直在努力寻找解决方案多天。 如果您有任何线索或解决方案,请告诉我。

谢谢。

我正在处理同样的问题,我认为,最后,实际上我找到了一个解决方法,我不是专业程序员,但这是我的解决方案:

  public Task ReleaseSingleImageMemoryTask(MyImage myImage, object control) { Pivot myPivot = control as Pivot; Task t = Task.Factory.StartNew(() => { Deployment.Current.Dispatcher.BeginInvoke(() => { if (myImage.img.UriSource != null) { myImage.img.UriSource = null; DisposeImage(myImage.img); } PivotItem it = (PivotItem)(myPivot.ItemContainerGenerator.ContainerFromIndex(myImage.number % 10)); Image img = FindFirstElementInVisualTree(it); if (img != null) { img.Source = null; GC.Collect(); } }); myImage.released = true; }); return t; } private T FindFirstElementInVisualTree(DependencyObject parentElement) where T : DependencyObject { var count = VisualTreeHelper.GetChildrenCount(parentElement); if (count == 0) return null; for (int i = 0; i < count; i++) { var child = VisualTreeHelper.GetChild(parentElement, i); if (child != null && child is T) { return (T)child; } else { var result = FindFirstElementInVisualTree(child); if (result != null) return result; } } return null; } private void DisposeImage(BitmapImage img) { if (img != null) { try { using (var ms = new MemoryStream(new byte[] { 0x0 })) { img = new BitmapImage(); img.SetSource(ms); } } catch (Exception e) { System.Diagnostics.Debug.WriteLine("ImageDispose FAILED " + e.Message); } } } 

希望这有帮助:)