9

私はWP7アプリに取り組んでいます。これは、基本的なズームとフリックジェスチャが実装された画像ギャラリーアプリです。

テストの目的で、オフライン画像(ファイル名には番号が付けられています)をContentに設定してアプリをコンパイルし、ハードコードされた文字列(後で置き換えられます)を介してアクセスしました。

しかし、アプリが大量のメモリを消費することに気づきました。画像によるものだと思い、このブログを見つけました; 画像は常にキャッシュされていました。これを修正するためにブログのコードを使用しました。それでも、消費率は低下しましたが、メモリは解放されません。

最後の試みとして、ナビゲーション用の基本機能2ボタンと画像の画像制御を備えた別のテストアプリを作成しました。これは、問題になる可能性があるのがジェスチャーコードではないことを確認するためです。

これはxamlです

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Image Grid.Row="0" x:Name="ImageHolder" Height="Auto" Width="Auto" Stretch="Uniform" Tap="image_Tap" />
    <TextBlock x:Name="MemUsage" />
    <StackPanel Grid.Row="1" Orientation="Horizontal">
        <Button x:Name="PrevButton" Content="Prev" Width="240" Click="btnPrev_Click"/>
        <Button x:Name="NextButton" Content="Next" Width="240" Click="btnNext_Click"/>
    </StackPanel>
</Grid>

これは.csファイルです

    const int PAGE_COUNT = 42;
    int pageNum = 0;
    public MainPage()
    {
        InitializeComponent();
        RefreshImage();
    }

    private void btnPrev_Click(object sender, RoutedEventArgs e)
    {
        pageNum = (PAGE_COUNT + pageNum - 1) % PAGE_COUNT; // cycle to prev image
        RefreshImage();
    }

    private void btnNext_Click(object sender, RoutedEventArgs e)
    {
        pageNum = (PAGE_COUNT + pageNum + 1) % PAGE_COUNT; // cycle to next image
        RefreshImage();
    }

    private void image_Tap(object sender, GestureEventArgs e)
    {
        RefreshTextData();
    }

    private void RefreshImage()
    {
        BitmapImage image = ImageHolder.Source as BitmapImage;
        ImageHolder.Source = null;
        if (image != null)
        {
            image.UriSource = null;
            image = null;
        }
        ImageHolder.Source = new BitmapImage(new Uri("000\\image" + (pageNum + 1).ToString("D3") + ".jpg", UriKind.Relative));
        RefreshTextData();
    }

    private void RefreshTextData()
    {
        MemUsage.Text = "Device Total Memory = " + (long)DeviceExtendedProperties.GetValue("DeviceTotalMemory") / (1024 * 1024)
            + "\nCurrent Memory Usage = " + (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage") / (1024 * 1024)
            + "\nPeak Memory Usage = " + (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage") / (1024 * 1024);
    }

しかし、それでもメモリリークがあり、特定できません。私はそれを見つけるのに苦労しています。メモリプロファイラーは、文字列のインスタンスが多数あることを示していますが、それを解釈することはできません。

いくつかのポイント:

  • 「000」フォルダに「image###」という名前の画像があります。現在、「image001」から「image042」までのファイル名の画像があります
  • テストアプリのメモリフットプリントは、最初のページが画像とともに完全に表示されるとすぐに6 MBになり、最初のページを変更すると、ほぼ18〜20MBになります。
  • その後のページ変更により、メモリが徐々に増加し、画像の数が許せば最終的にクラッシュします。それ以外の場合は、すべての画像を循環した後、メモリ消費量は一定です。
  • 約1280x2000のサイズの.jpgファイルを使用していますが、テスト用に画像のサイズを変更していません。

ヒープの概要->新しい割り当て

4

4 に答える 4

6

私は同じ種類のアプリを持っていますが、次/前の画像ボタンがあります。そして、まったく同じメモリリークが発生したため、私は怒りました。

私はまだ根本的な原因を見つけることができませんでしたが、醜いハックでそれを回避することができました。次の画像を表示するときに、古い画像ソースに無効な画像を強制的にロードして、メモリを解放します。すべての参照を削除してガベージコレクターを呼び出すだけでは不十分な理由がわかりません。内部のどこかに別の参照が保持されている必要があります。

とにかく、ここにハックがあります:

private void DisposeImage(BitmapImage image)
{
    if (image != null)
    {
        try
        {
            using (var ms = new MemoryStream(new byte[] { 0x0 }))
            {
                image.SetSource(ms);
            }
        }
        catch (Exception)
        {
        }
    }
}

たとえば、RefreshImageメソッドで呼び出すことができます。

private void RefreshImage()
{
    BitmapImage image = ImageHolder.Source as BitmapImage;
    ImageHolder.Source = null;

    DisposeImage(image);

    ImageHolder.Source = new BitmapImage(new Uri("000\\image" + (pageNum + 1).ToString("D3") + ".jpg", UriKind.Relative));
    RefreshTextData();
}

ちょっとそれを使うのは恥ずかしいですが、少なくともそれはうまくいくようです。

于 2012-11-20T21:36:54.037 に答える
1

コードサンプルを試しましたが、Windows Phone 8環境では、リークを再現できませんでした。唯一の違いは、私が自分の画像を使用したことです。

512 WVGAエミュレータの現在のメモリ使用量は13MBのままで、Peakは14MBのままでした。「次へボタン」を約20回押しました。

また、ソースを手動で設定する代わりに、ImageHolderのバインディングを使用してみましたか?

(ところで、視覚的には、コードビハインドでメモリリークが発生する可能性はありません)。

(この記事も確認してくださいhttp://blogs.windows.com/windows_phone/b/wpdev/archive/2012/02/01/memory-profiling-for-application-performance.aspx

于 2012-11-16T08:18:08.857 に答える
1

多くの試行とデバッグセッションを行った後、画像がアプリのIsolatedStorageにある場合、この画像のキャッシュは実行されない(または積極的に実行されない)ことがわかりました。

xapファイルの一部であり、コンテンツとして含まれている画像を使用していました。画像ビューアをテストしたかったので、これを行いました。しかし、これは私のアプリが終了する場合には当てはまりません。アプリは、画像を分離ストレージに保存して表示するように設計されています。

そこで、必要なコードと出来上がりを設定しました。画像はまだキャッシュされていますが、ガベージコレクションが行われています。下の画像を参照してください(ガベージコレクタが呼び出される回数を参照してください)。これはそれほど些細な質問に対する解決策であり、それが他の誰もこの種の問題に直面しなかった理由です。

WP7 Silverlightは、画像が分離ストレージからのものではないことを検出すると、画像がリモートURIからのものであると想定し、とにかくそれをキャッシュすることを決定すると思います。そして、そこでSilverlightイメージキャッシングの問題が発生します。別の回答が確認しているように、これはWP8では発生しません。ここに画像の説明を入力してください

于 2012-11-21T06:02:13.610 に答える
0

このアプローチを試してください:自動メモリクリーニングを備えた画像ダウンローダー。これは、視覚化をサポートする高度なKooKiZのサンプルです。サンプルプロジェクトはこちら:https ://simca.codeplex.com/

于 2013-10-02T19:39:53.030 に答える