2012-04-09 3 views
2

ステファンウィックは、私たちが、私は彼の例をテストしているWindowsPhoneで画像キャッシュをクリアする方法7. UriSourceをnullに設定しても機能しません! WP7でイメージキャッシュをクリアするには、他にどのような方法がありますか?プロジェクト(ImageTips.zip) -

<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

のようなコードを使用してWP7で画像キャッシュをクリアすることができ、彼のブログに書いています - - そして私は、上記のコードは動作しないと言うことができます---キャッシュされたイメージのメモリを解放せず、アプリケーションのキャッシュされたイメージを削除しません。

UriSourceをnullに設定すると、ページCaching.xamlのメモリが解放されますが、MainPage.xamlに戻るとメモリが解放されないことがわかります---メモリが増加しています!!!私の観察を再現するために、我々はステファンのプロジェクトを使用することができることを確認するには

---彼のブログでImageTips.zip ...

Test project ImageTips.zip

---次のことができます。メインページにする 1.追加コードあなたのCaching.xamlページ上のような現在のメモリ値を表示するための.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(Image caching)に移動します。メモリの値はほぼ9011200バイトです。
  3. ボタンをクリックします。画像表示するショー - メモリの値が413696のバイトをdissapearedてき避けイメージキャッシュ(キャッシュされた画像をクリアする)とクリアその押しボタンの後--- 10090144のバイト....だから、上のほぼ12996608バイト
  4. クリックに等しいですか? ?? (10090144 - 9676448 = 413696バイト)
  5. ボタンをクリックすると、MainPage.xaml --- 11828248 bytesに戻ることができます。ただし、Caching.xamlにナビゲートする前の以前の値は9676448バイトでした...だから、 2151800バイト????

    Caching.xaml(画像を表示してキャッシュで画像を消去する)を20回移動し、MainPage.xamlに戻ると、使用メモリは3.3MBに増加します。

私のアプリケーションでこの問題が発生し、解決方法がわかりません。

Windows phone 7でイメージキャッシュをクリアするには、他にどのような方法がありますか? 、またはUriSourceをnullに設定してイメージキャッシュをクリアすると、前のページに戻るときにメモリが解放されません。

ありがとうございました。

+0

私は窓の電話についてゼロの隣に知っているので、これは答えではなくコメントとして残しています。これがWindowsデスクトップアプリケーションの場合は、GCがまだ実行されていないと言えるでしょう。したがって、OOMの表示を開始しない限り、心配することはありません。そのアドバイスがWindowsの電話機に保持されているかどうかは不明です。 –

+0

WP7は、グローバルルート上の参照に何らかの形で保持されている.NETの「メモリリーク」を起こしやすくなりますが、ほとんど同じことです。 –

答えて

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 ext:ImageExtension.Source = "{SomeSource}"/> そこにキャッシュのクリアを処理するが、私はそれの必要性を持っていなかった。

+0

GCはすべてのチックで呼び出されます...あなたは他の場所でのメモリリークについて言いました---しかし、ブログで与えられた例は最も簡単です... 2MBをここで失ったかどうかは関係ありません---しかし、Caching.xamlをページングする(画像を表示し、キャッシュで画像を消去するをクリックする)と、MainPage.xamlに戻るときには、メモリを3.3MBに増やすために20回移動すると... 私のアプリケーションでは、その上に1つのイメージを持つページがあり、250以上の異なるイメージが開きます。だから---すべての画像をキャッシュした結果、約30MBのメモリリークがあります。 –

+0

あなたのページにデストラクタを追加して、呼び出されているかどうかを確認してください。 〜YourPage(){Deployment.Current.Dispatcher.BeginInvoke(()=> {MessageBox.Show( "PAGENAMEはGCを取得しました")}); }私はそれがGCを得るのを妨げるdispatchertimerかもしれないと思う。したがって、メモリを見るには、メッセージボックスをトリガーする単純なボタンを使用します。私はメモリカウンタウィジェットを持つCoding 4 fun toolkitを一度使ったことを覚えています。すべてがうまくいっていたが、GCを取得するページが表示されなかった。私は内部的にそれもディスパッチャーを使ったと信じています。 – krdx

関連する問題