3

サムネイルのリストを表示する Windows phone アプリケーションを作成しています。私はそれを行うために LongListSelector を使用しています。

サムネイル リストを何度か前後に移動すると、アプリケーションでメモリ リークが発生します。アプリの使用中にメモリ使用量を確認したところ、サムネイルのあるページを開くとメモリが増加していることがわかります (予想どおり)。前のページに戻ると、メモリ使用量は減少しますが、増加するほどではありません。プロセスを数回繰り返すと、メモリ不足の例外で終了します。

2 ページのみのテスト アプリケーションを作成しました。1 つは、LongListSelector に一連の potos をロードする他に移動するためのボタンを備えています。このアプリを作成して、メモリ リークが他の原因によるものではないことを確認します。

この簡単なテストでは、メモリ使用量はアプリと同じように動作します。

サムネを含む私のページのメインコードは次のとおりです。

public class testObject
{
    public string Title { get; set; }
    public BitmapImage Thumbnail { get; set; }
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{

    photosList = new List<testObject>();
    for (int i = 0; i < 200; i++)
    {
        BitmapImage bi = new BitmapImage(new Uri("/images/"
                                        + i.ToString()+".jpg",
                                        UriKind.RelativeOrAbsolute));


        photosList.Add(new testObject { Title = i.ToString(),
                                            Thumbnail = bi });
    }

    GridPictures.ItemsSource = photosList;

}

protected override void OnBackKeyPress(
            System.ComponentModel.CancelEventArgs e)
{
    foreach (testObject test in photosList)
    {
        test.Thumbnail.DecodePixelHeight = 1;
        test.Thumbnail.DecodePixelWidth = 1;
        test.Thumbnail = null;
    }
    photosList.Clear();
    photosList = null;

    base.OnBackKeyPress(e);
}

そして、他のページのボタンのコードは次のとおりです。

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.RelativeOrAbsolute));

}
4

1 に答える 1

2

LongListSelectorリークの既知のソースです。Imageこれらのリークは、大量のメモリを使用する のようなコントロールを使用している場合に特に厄介になります。

これまでの最善の解決策は、LongListSelector を完全に避けることです。ただし、適切な代替手段が見つからない場合は、いくつかの回避策があります。

  • Page1 では、OnNavigatedFromイベントで、写真の解放を強制します。これを行うにはいくつかの方法がありますが、通常はImageSourceプロパティを null に設定するだけで十分です

  • 面倒な作業を行うカスタム コントロールを作成する

カスタム コントロールは次のようになります。

public class SafePicture : System.Windows.Controls.ContentControl
{
    public SafePicture()
    {
        this.Unloaded += this.SafePictureUnloaded;
    }

    private void SafePictureUnloaded(object sender, System.Windows.RoutedEventArgs e)
    {
        var image = this.Content as System.Windows.Controls.Image;

        if (image != null)
        {
            image.Source = null;
        }
    }
}

次に、すべての画像をそのコントロールにラップします。

<my:SafePicture>
    <Image Source="{Binding Path=Thumbnail}" />
</my:SafePicture>

そして、それはうまくいくはずです。それでもメモリリークが発生することに注意してください。ただし、はるかに妥当な量です。

于 2013-07-05T18:38:27.587 に答える