Memory consumption of BitmapImage/Image control in Windows Phone 8
I am testing a WP8 app and it's image viewer to show many images, I found
app's memory consumption is raising and want to find out how to solve it.
I've read some articles from web, however the solutions provided by those
articles are not working on my app, please read the history below.
First, I found the article "Image Tips for Windows Phone 7" and download
its sample to do clean image cache testing, it's working with 1 image.
And then for testing purposes, I make this app compiled with 15 offline
images inside the app, and set as "Content", please download test app from
here.
My testing steps are:
(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
When I'm testing my app, the memory is raising, like 16.02MB =>
Show(19.32MB) => Clear(16.15MB) => Show(20.18MB) => Clear (17.03MB)...etc
And memory won't be freed even leaving caching page and go to caching page
again. It seems the solution of article "Image Tips for Windows Phone 7"
is working for only 1 image.
Here comes the xaml and code-behind of solution by "Image Tips for Windows
Phone 7".
[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";
}
}
I also tried to search any other solutions, some testing results are as
below.
(1) Article "[wpdev] Memory leak with BitmapImage": It provides 2
solutions, one is DisposeImage API, another is to set BitmapImage source
to null as below. Also the article let us know we must be careful about
event handler attach/dettach, however my testing app doesn't have event
handler in caching page.
[DisposeImage]
private void DisposeImage(BitmapImage image)
{
if (image != null)
{
try
{
using (var ms = new MemoryStream(new byte[] { 0x0 }))
{
image.SetSource(ms);
}
}
catch (Exception)
{
}
}
}
[Set null]
BitmapImage bitmapImage = image.Source as BitmapImage;
bitmapImage.UriSource = null;
image.Source = null;
(2) Article "Windows phone: listbox with images out-of-memory": It
provides an API "DisposeImage" with little difference than (1)'s as below,
but this also doesn't work, I still got the memory raising symptom.
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) Article "Cannot find the memory leak": It provides the same 2
solutions as above mentioned, also it mentioned the issue cannot repro for
isolated storage's images, however my testing app's images are from
isolated storage.
(4) I also tried for 1000 images, the testing result is app crash when the
app showed around 190 images sequentially, please refer to the Windows
Phone Application Analysis Graphics for memory below.
Finally, thanks for your patience to read my question and history, I've
been working on this to find solution for many days. If you have any clue
or solution, please kindly let me know.
Thanks.
No comments:
Post a Comment