找不到内存泄漏
我一直在研究WP7应用程序,它是图像库应用程序,实现了基本的缩放和轻弹手势。
出于测试目的,我使用设置为Content的离线图像(其文件名已编号)编译应用程序,并通过硬编码字符串(稍后将替换)访问它们。
但后来意识到应用消耗了大量内存。 我以为这是由于图像并发现了这个博客 ; 图像总是缓存。 我使用博客中的代码来纠正这个问题。 尽管消费率确实下降,但仍未释放内存。
为了最后的尝试,我创建了另一个带有基本function2按钮的测试应用程序,用于图像的导航和图像控制,只是为了确保它不是我的手势代码可能是问题。
这是xaml
这是.cs文件
const int PAGE_COUNT = 42; int pageNum = 0; public MainPage() { InitializeComponent(); RefreshImage(); } private void btnPrev_Click(object sender, RoutedEventArgs e) { pageNum = (PAGE_COUNT + pageNum - 1) % PAGE_COUNT; // cycle to prev image RefreshImage(); } private void btnNext_Click(object sender, RoutedEventArgs e) { pageNum = (PAGE_COUNT + pageNum + 1) % PAGE_COUNT; // cycle to next image RefreshImage(); } private void image_Tap(object sender, GestureEventArgs e) { RefreshTextData(); } private void RefreshImage() { BitmapImage image = ImageHolder.Source as BitmapImage; ImageHolder.Source = null; if (image != null) { image.UriSource = null; image = null; } ImageHolder.Source = new BitmapImage(new Uri("000\\image" + (pageNum + 1).ToString("D3") + ".jpg", UriKind.Relative)); RefreshTextData(); } private void RefreshTextData() { MemUsage.Text = "Device Total Memory = " + (long)DeviceExtendedProperties.GetValue("DeviceTotalMemory") / (1024 * 1024) + "\nCurrent Memory Usage = " + (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage") / (1024 * 1024) + "\nPeak Memory Usage = " + (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage") / (1024 * 1024); }
但仍有内存泄漏,我无法指出它。 我很难找到它。 内存分析器显示我有很多字符串实例,我无法解释。
几点:
- 我在“000”文件夹中有图像并命名为“image ###”。 目前我的图像文件名从“image001”到“image042”
- 一旦完整显示第一页图像,测试应用程序的内存占用量为6 MB,在fisrt页面更改后,它上升到大约18-20 MB
- 如果图像数量允许,后续页面更改会导致内存逐渐增加然后最终崩溃,否则在循环通过所有图像后内存消耗将保持不变
- 我正在使用大小为1280 x 2000的.jpg文件,用于测试我没有调整图像大小。
新分配”>
我有相同类型的应用程序,下一个/上一个图片按钮。 我有完全相同的内存泄漏,这让我很生气。
我仍然无法找到根本原因,但我已经成功绕过了丑陋的黑客。 当显示下一张图片时,我强制旧图像源加载无效图片,从而释放内存。 我不明白为什么删除所有引用并调用垃圾收集器是不够的,必须在内部保留另一个引用。
无论如何,这是黑客:
private void DisposeImage(BitmapImage image) { if (image != null) { try { using (var ms = new MemoryStream(new byte[] { 0x0 })) { image.SetSource(ms); } } catch (Exception) { } } }
您可以在RefreshImage
方法中调用它:
private void RefreshImage() { BitmapImage image = ImageHolder.Source as BitmapImage; ImageHolder.Source = null; DisposeImage(image); ImageHolder.Source = new BitmapImage(new Uri("000\\image" + (pageNum + 1).ToString("D3") + ".jpg", UriKind.Relative)); RefreshTextData(); }
有点惭愧使用它,但至少它似乎工作。
我已经尝试过您的代码示例,但在Windows Phone 8环境中,我无法重现泄漏。 唯一的区别是我使用了自己的图像。
我的512 WVGA仿真器的当前内存使用率保持在13MB,峰值保持在14MB。 我把“下一个按钮”推了大约20次。
您是否尝试过使用ImageHolder的Bindings而不是手动设置Source?
(顺便说一下,在视觉上我没有看到你的代码隐藏中有任何可能的内存泄漏)。
(另请参阅此文章http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/02/01/memory-profiling-for-application-performance.aspx )
经过多次试运行和调试会话后,我发现当图像驻留在应用程序的IsolatedStorage中时,不会执行图像缓存(或者不会执行积极的图像缓存)。
事情是我使用的图像是xap文件的一部分,包含在内容中。 我这样做是因为我只想测试我的图像查看器。 但是,当我的应用程序完成时,情况并非如此。 应用程序的设计目的是将图像存储在独立存储中并显示它们。
所以我设置了必要的代码,瞧,图像现在正在收集垃圾,即使它们仍然被缓存。 请参见下图(查看垃圾收集器调用的次数)。 这是一个不那么微不足道的问题的解决方案,这就是为什么没有其他人遇到这种问题的原因。
我相信当WP7 silverlight发现图像不是来自隔离存储时,它假定图像来自某个远程URI,并决定无论如何都要缓存它。 而这就是Silverlight图像缓存问题的解决方案。另一个答案证实,这不会发生在WP8中。
尝试这种方法: 具有自动内存清理function的图像下载器 。 它是先进的KooKiZ样本,支持可视化。 示例项目位于: https : //simca.codeplex.com/