5

たくさんの画像が入った ListBox があります (datatemplate を使用して行います)。画像は、アイテム ソースを設定することによって作成されます。

<Image x:Name="ItemImage" Source="{Binding ImageUrl}"/> 

その後、リストボックスの Items.Clear() メソッドを使用してクリアされます。リストボックスの Items.Add メソッドを使用して、新しい画像を追加します。

ただし、メモリ使用量はどんどん増えていきます。表示されるのは同じ 300 ほどの小さな画像ですが、メモリが解放されることはないようです。アプリは約 40 メグを使用し始め、すぐに 700 メグまで上昇します。これらすべてのイメージが使用しているメモリを解放するにはどうすればよいですか?

編集:私が言及するのを忘れたことの1つは、画像(サイズはそれぞれ約4〜5k)がネットワーク経由でロードされていることです。キャッシングはこれに何らかの責任がありますか?12 個の画像を表示すると、約 10 メガバイトのメモリが消費されます。これはファイルサイズの約 100 倍です。

4

2 に答える 2

4

画像を読み込むときに何か異常なことをしている場合(自家製の画像ローダーなどを使用している場合など)を除いて、GCは、画像を参照しなくなったときに画像を消去する必要があります。

どこかでデータへの参照を保持していますか?イベントとイベントハンドラーは、ガベージコレクターをだまして、オブジェクトがまだ使用されていると思わせることがあることを忘れないでください。

MyObject obj = new MyObject();
obj.TheEvent += new EventHandler(MyHandler);
obj = null;
// Now you might think that obj is set for collection but it 
// (probably - I don't have access to MS' .NET source code) isn't 
// since we're still listening to events from it.

これがあなたに当てはまるかどうかはわかりませんが、少なくとも私があなたであるかどうかを確認しました。

また、AQTimeなどのプロファイラーにアクセスできる場合は、コードを実行するとヒントが得られる場合があります。

また、ディスクまたはアセンブリに埋め込まれたリソースからイメージをロードする場合に、違いが生じるかどうかを確認することもできます。

于 2008-10-09T12:08:48.557 に答える
4

そもそもそのメモリを使い果たしてはどうでしょうか。

注:次の段落とコードは、この回答から複製されています。)

問題の一部は、それぞれに完全な画像をロードしていることです。のまたはプロパティのいずれかを設定して、を使用IValueConverterしてサムネイルサイズで各画像を開く必要があります。これが私のプロジェクトの1つで使用する例です...DecodePixelWidthDecodePixelHeightBitmapImage

class PathToThumbnailConverter : IValueConverter {
    public int DecodeWidth {
        get;
        set;
    }

    public PathToThumbnailConverter() {
        DecodeWidth = 200;
    }

    public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
        var path = value as string;

        if ( !string.IsNullOrEmpty( path ) ) {

            FileInfo info = new FileInfo( path );

            if ( info.Exists && info.Length > 0 ) {
                BitmapImage bi = new BitmapImage();

                bi.BeginInit();
                bi.DecodePixelWidth = DecodeWidth;
                bi.CacheOption = BitmapCacheOption.OnLoad;
                bi.UriSource = new Uri( info.FullName );
                bi.EndInit();

                return bi;
            }
        }

        return null;
    }

    public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
        throw new NotImplementedException();
    }

}

コンバーターがバックグラウンドスレッドで呼び出されるように、を検討IsAsync=Trueすることもできます。Binding

于 2008-10-09T16:19:07.427 に答える