Потребление памяти управления BitmapImage / Image в Windows Phone 8
Я тестирую приложение 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.02 MB => показать (19.32 MB) => очистить ( 16.15 MB) = > показать (20.18 MB) = > очистить (17.03 MB)...так далее И память не освободитесь, даже оставив страницу кэширования, и снова перейдите на страницу кэширования. Кажется, решение статьи "советы по изображению для Windows Phone 7" работает только для 1 изображения.
вот xaml и код-за решением"советы по изображению для Windows Phone 7".
[кэширования.язык 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>
[кэширования.код 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, как показано ниже. Также в статье мы должны быть осторожны с обработчиком событий attach / dettach, однако мое приложение для тестирования не имеет обработчика событий на странице кэширования.
[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) статьи "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 изображений последовательно, обратитесь к графическому анализу приложений Windows Phone для памяти ниже.
наконец, спасибо за ваше терпение, чтобы прочитать мой вопрос и историю, я работал над этим, чтобы найти решение в течение многих дней. Если у вас есть какие-либо подсказки или решения, пожалуйста, сообщите мне об этом.
спасибо.
1 ответов
Я имел дело с той же проблемой, и я думаю, в конце концов, что на самом деле я нашел решение, я не профи программист, но вот мое решение:
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<Image>(it);
if (img != null)
{
img.Source = null;
GC.Collect();
}
});
myImage.released = true;
});
return t;
}
private T FindFirstElementInVisualTree<T>(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<T>(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);
}
}
}
надеюсь, что это поможет :)