2

Stefan Wick は彼のブログで、次のようなコードを使用して WP7 の画像キャッシュをクリアできると書いています。

<code>
  BitmapImage bitmapImage = image.Source as BitmapImage;
  bitmapImage.UriSource = null;
  image.Source = null;

http://blogs.msdn.com/b/swick/archive/2012/04/05/10151249.aspx?CommentPosted=true#commentmessage

彼の例 -- プロジェクト (ImageTips.zip) --- をテストしましたが、上記のコードは機能しないと言えます --- キャッシュされた画像のメモリを解放せず、アプリケーションのキャッシュされた画像を削除しません。

UriSource を null に設定すると -- ページ Caching.xaml のメモリのみが解放されますが、MainPage.xaml に戻ると --- メモリが解放されていないことがわかります --- メモリが増加しました!!!

Stefan のプロジェクト --- 彼のブログの ImageTips.zip を使用できることを確認するには...

プロジェクトのテスト ImageTips.zip

私の観察を再現するには --- 次のことができます。 1. Caching.xaml ページのように現在のメモリ値を表示するコードを MainPage.xaml に追加します。

<tab>

        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"));
        };
</code>
  1. アプリケーションを実行します。初めて MainPage.xaml に移動すると、メモリの値はほぼ 9676448 バイトになります。
  2. クリックして Caching.xaml (画像キャッシュ) に移動します --- メモリの値はほぼ 9011200 バイトです
  3. [表示] ボタンをクリックして画像を表示します -- メモリの値はほぼ 12996608 バイトです
  4. [画像キャッシュを回避] をクリックし (キャッシュされた画像をクリアするには)、その後 [クリア] ボタンを押します --- 10090144 バイト .... 413696 バイトはどこで消えましたか ??? (10090144 - 9676448 = 413696 バイト)
  5. [戻る] ボタンをクリックして MainPage.xaml に戻ります --- 11828248 バイト... しかし、Caching.xaml に移動する前の以前の値は 9676448 バイトでした... では、2151800 バイトがどこで消えたのでしょうか??

    Caching.xaml のページに 20 回移動し ([画像を表示] をクリックしてキャッシュ付きの画像をクリア)、MainPage.xaml に戻ると --- 使用メモリは 3.3 MB に増加します... など

アプリケーションでこの問題に遭遇しましたが、解決方法がわかりません。

Windows phone 7 で画像キャッシュをクリアする他のバリアントは? または、UriSource を null に設定して画像キャッシュをクリアすると、前のページに戻るときに機能しない (メモリが解放されない) のはなぜですか?

ありがとう。

4

1 に答える 1

6

ブログに記載されている例が機能することを保証できます。この例で扱っているメモリの量は非常に小さく、あちこちで 2MB を「失った」かどうかは問題ではないことに注意してください。おそらく、GC が開始されていないか、その間に他のオブジェクトが割り当てられたためです。(実際に重大なリークが発生した場合は、コードの他の場所を確認する必要があります)

私自身のアプリケーションでは、たくさんの画像を扱っています。いつでも最大 60 MB のメモリを消費します。そのため、認証に合格するためにメモリリークが発生しないように非常に妄想的でした。

ブログの例では、プログラムで画像を追加していること、および画像にアクセスできることを前提としているため、ソースを null に設定できます。

  BitmapImage bitmapImage = image.Source as BitmapImage;
  bitmapImage.UriSource = null;
  image.Source = null;

これだけで、画像のキャッシュを防ぐことができます。

ただし、データ バインディングを使用している場合は、画像のキャッシュを防止するのは簡単ではないことにすぐに気付くでしょう。

データ バインディングを使用するアプリケーションでは、次のような設定を行いました。

リストボックスに画像を表示したいとしましょう。

//MainPage.xaml
<StackPanel>
<ListBox ItemsSource="{Binding Pictures}">
    <ListBox.ItemTemplate>
       <DataTemplate>
          <Image MaxHeight="1000" Source="{Source}" />
       </DataTemplate>
    </ListBox.ItemTeplate>
</ListBox> 
<Button Tap="LoadImages_Tap" Content="Load Images" />
</StackPanel> 

-

 //Picture.cs
    public class Picture
    { 
        private BitmapImage _source = new BitmapImage()
        {
            CreateOptions = BitmapCreateOptions.BackgroundCreation | BitmapCreateOptions.IgnoreImageCache | BitmapCreateOptions.DelayCreation
        };

        public Picture(string url) {
            _source.UriSource = new Uri(url, UriKind.Absolute);
        }

        public BitmapImage Source
        {
            get
            {
                return _source;
            } 
        } 

    }
}


//MainPage.xaml.cs
private ObservableCollection<Picture> _pictures = new ObservableCollection<Picture>();
public ObservableCollection<Picture> Pictures {
  get {
   return _pictures;
  }
}
public MainPage() {
  //...
  DataContext = this;
}

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
        if (e.NavigationMode == NavigationMode.Back)
        {
            PreventCaching();
            _pictures.Clear();
        }
        base.OnNavigatedFrom(e);
}  

private void PreventCaching() {
   foreach(var picture in _pictures) {
     picture.Source.UriSource = null;
   }
}
private void LoadPictures_Tap(object sender, EventArgs e) { 
     PreventCaching();
    _pictures.Clear();
    foreach(var url in SomeMethodThatReturnsUrlsForImages()) {  
      _pictures.Add(new Picture(url));
    }
}

上記は、データ バインディングを使用している場合 (<Image> 要素に直接アクセスできない場合)、画像キャッシュをクリアする必要があります。

または、おそらくカスタムの添付依存関係プロパティを作成することもできるので、これを行うことができます: <Image ext:ImageExtension.Source="{SomeSource}" /> そこでキャッシュのクリアを処理しますが、その必要はありませんでした。

于 2012-04-09T16:33:35.877 に答える