Testuję aplikację WP8 i jej przeglądarkę obrazów, aby wyświetlić wiele obrazów. Zauważyłem, że zużycie pamięci aplikacji rośnie i chcę się dowiedzieć, jak go rozwiązać.Zużycie pamięci BitmapImage/Kontrola obrazu w Windows Phone 8
Czytałem niektóre artykuły z internetu, jednak rozwiązania dostarczone przez te artykuły nie działają na mojej aplikacji, zapoznaj się z historią poniżej.
Po pierwsze, uważam, że artykuł „Image Tips for Windows Phone 7” i pobrać jej próbkę do badań należy czyścić cache obraz, to działa z 1 obrazek.
A potem do celów testowych, robię to aplikacja przygotowana z 15 obrazów w trybie offline wewnątrz aplikacji i ustawić jako „Content”, należy pobrać testową aplikację z here.
Moi etapy testowania są:
(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
Kiedy jestem testowania mojej aplikacji, pamięć jest drapanie, jak 16.02MB => Show (19.32MB) => clear (16.15MB) => Pokaż (20.18MB) => Wyczyść (17.03MB) ... itd. Pamięć nie zostanie zwolniona nawet po opuszczeniu strony pamięci podręcznej i ponownym przejściu do strony buforowania. Wygląda na to, że rozwiązanie artykułu "Image Tips for Windows Phone 7" działa tylko dla 1 obrazu.
Nadchodzi kod xaml i kodu źródłowego rozwiązania "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";
}
}
że próbował również do wyszukiwania innych rozwiązań niektóre wyniki testów podano poniżej.
(1) Artykuł "[wpdev] Memory leak with BitmapImage": Dostarcza 2 rozwiązania, jednym jest DisposeImage API, innym jest ustawienie źródła BitmapImage na wartość null, jak poniżej. Również w tym artykule informujemy, że musimy uważać na obsługę dołączania/dettach zdarzeń, jednak moja aplikacja do testowania nie ma obsługi zdarzeń na stronie buforowania.
[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) Artykuł "Windows phone: listbox with images out-of-memory": To zapewnia API "DisposeImage" z małą różnicą niż (1) jak poniżej, ale to też nie działa, wciąż mam symptomy powodujące wzrost pamięci.
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) Artykuł „Cannot find the memory leak”: Zapewnia te same 2 rozwiązania, jak wyżej wspomniano, również on wymieniony problem nie może powtórzenia błędu dla obrazów samodzielnie magazynowania, jednak obrazy moich testów aplikacji są z izolowanym przechowywania.
(4) Próbowałem również na 1000 zdjęć, wynikiem testu jest awaria aplikacji, gdy aplikacja wyświetla sekwencyjnie około 190 obrazów, zapoznaj się z grafiką analizy aplikacji systemu Windows Phone dla pamięci poniżej.
Wreszcie, dziękuję za cierpliwość, aby przeczytać moje pytanie i historię, pracuję nad tym, aby znaleźć rozwiązanie na wiele dni. Jeśli masz jakąkolwiek wskazówkę lub rozwiązanie, uprzejmie proszę dać mi znać.
Dzięki.
Dobre pytanie, mają te same problemy. Jakieś wieści tutaj? –
Ciągle szukam rozwiązania. Wygląda na to, że jest to błąd WP7.5, co oznacza, że dzieje się tak również na WP8, ale nie atakujesz tylko WP8. –