我正在测试一款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]
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<ToggleButton Content="Show" Width="150" Checked="ShowImageClicked" Unchecked="ClearImageClicked"/>
<CheckBox x:Name="cbAvoidCache" Content="Avoid Image Caching"/>
</StackPanel>
<Image x:Name="img" Grid.Row="2" Width="256" Height="192"/>
<TextBlock x:Name="tbMemory" Grid.Row="2" Text="Memory: " VerticalAlignment="Bottom" Style="{StaticResource PhoneTextLargeStyle}"/>
</Grid>
[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": 它提供了两种解决方案,一种是使用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: listbox with images out-of-memory":它提供了一个名为"DisposeImage"的API,与(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个图像时,应用程序会崩溃,请参考下面的Windows Phone应用程序分析图形中的内存。
最后,感谢您耐心阅读我的问题和历史,我已经为此工作多天,寻找解决方案。 如果您有任何线索或解决方案,请友好地让我知道。
谢谢。