WP8 アプリをテストしていますが、多くの画像を表示する画像ビューアーです。アプリのメモリ消費量が増えていることがわかり、解決方法を知りたいと考えています。
Web からいくつかの記事を読みましたが、それらの記事で提供された解決策がアプリで機能しません。以下の履歴をお読みください。
まず、「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 => Show(19.32MB) => Clear( 16.15MB ) => Show(20.18MB) => Clear ( 17.03MB )...などのようにメモリが増加しています そしてメモリキャッシングページを離れて再度キャッシングページに移動しても解放されません。記事「Windows Phone 7 の画像のヒント」の解決策は、 1 つの画像に対してのみ機能しているようです。
「 Image Tips for Windows Phone 7 」によるソリューションの xaml とコード ビハインドは次のとおりです。
[キャッシング.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 によるメモリ リーク」: DisposeImage API と、以下のように BitmapImage ソースを null に設定するという 2 つの解決策を提供します。また、この記事では、イベント ハンドラーのアタッチ/デタッチに注意する必要があることを知らせていますが、私のテスト アプリにはキャッシュ ページにイベント ハンドラーがありません。
[画像を破棄]
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: メモリ不足の画像を含むリストボックス」: 以下のように (1) とほとんど変わらない API "DisposeImage" を提供していますが、これも機能しません。上げる症状。
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 アプリケーション分析グラフィックスを参照してください。
最後に、私の質問と履歴をお読みいただきありがとうございます。解決策を見つけるために何日も取り組んできました。何か手がかりや解決策がありましたら、お手数ですが教えてください。
ありがとう。