質問

画像をデータベースにキャプチャして保存するアプリケーションを開発しましたが、メモリ使用に関する問題が発生しています。私のドメインオブジェクトには、3つのプロパティがあります。

画像 - バイト配列、コンテンツはJPGです

RealimageThumb -BitMapImageに変換され、縮小されたバイト配列は、他のサムネイルと一緒にグリッドビューでユーザーに表示されます

RELEMAGE -BITMAPソースに変換されたバイト配列、セッターはありません。これは、ユーザーがその上に浮かぶときにツールチップに表示されます。

私が抱えている問題は、ユーザーが各画像の上に順番に順調に進んだ場合、メモリの使用状況がスパイラルスパイラルすることです。ユーザーがビットマップソースを覆い、メモリが解放されていないので、私はバッキングプロパティをRELIMAGEに与えて、これをnullに割り当てようとしましたが、メモリは解放されません(ゴミを待っていませんコレクタ?)。

編集:

これはあなたがレイの意味ですか?以下のようにツールチップに表示されているものは何もありませんが、定義しようとすると WeakReference<BitmapImage>, 、system.weakreferenceにはタイプパラメーターエラーがありません。

  private WeakReference _realImage;
        public virtual BitmapImage RealImage
        {
            get
            {
                if (_realImage == null || _realImage.Target == null)
                {

                    if (Image == null) return null;
                    var newBitmapImage = new BitmapImage();
                    newBitmapImage.BeginInit();
                    newBitmapImage.CacheOption = BitmapCacheOption.None;
                    newBitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                    newBitmapImage.StreamSource = new MemoryStream(Image);
                    newBitmapImage.EndInit();
                    _realImage = new WeakReference(newBitmapImage);
                }

                return (BitmapImage)_realImage.Target;
            }
        }
役に立ちましたか?

解決

あなたは3つのことをする必要があります:

  1. BitMapimageを構築するときは、StreamSourceを使用してデータを提供します。 Urisourceを使用したり、URIをコンストラクターに渡さないでください。これにより、画像が画像キャッシュに追加されます。

  2. ドメインオブジェクトのRELEMAGE実装では、BitMapImage自体ではなく、BitMapImageの弱者を保存します。 RELEMAGEが取得されると、WeakReferenceまたはWeakReference.targetがnullの場合、新しいBitmapimageと新しいWeakReferenceを作成します。

  3. テンプレートスイッチングを備えたデータストリガーを使用して、視覚ツリーに表示されているときのみの画像コントロールを含めることができます

ステップ3に必要なテンプレートを含むテンプレートは次のとおりです。

<DataTemplate x:Key="EmptyTemplate">
</DataTemplate>

<DataTemplate x:Key="RealImageTemplate">
  <Image Source="{Binding RealImage.Target}" Width="300" Height="300" />
</DataTemplate>

<DataTemplate x:Key="RealImageWhenVisible">

  <!-- Use EmptyTemplate when I am not visible -->
  <ContentPresenter x:Name="Presenter"
                    Content="{Binding}"
                    ContentTemplate="{StaticResource EmptyTemplate}"/>

  <!-- Switch to RealImageTemplate when I am visible -->
  <DataTemplate.Triggers>
    <DataTrigger Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}"
                 Value="True">
      <Setter TargetName="Presenter"
              Property="ContentPresenter.ContentTemplate"
              Value="{StaticResource RealImageTemplate}" />
    </DataTrigger>
  </DataTemplate.Triggers>
</DataTemplate>

これで、このようなツールチップを定義できます。

<Rectangle Width="40" Height="40" Fill="Blue">
  <Rectangle.ToolTip>
    <ContentPresenter Content="{Binding}"
                      ContentTemplate="{StaticResource RealImageWhenVisible}" />
  </Rectangle.ToolTip>
</Rectangle>

それがどのように機能するか:互いに2つのコンテンツプレセンターがあります:

  • 外側のContentSpresenterが見えない場合、内側のContentSpresenterにはemptyTemplateがあるため、画像はロードされません。
  • 外側のContentSpresenterが表示されると、内側のContentPresenterがRealimageTemplateを持ち、画像がロードされて表示されます。

これを行う必要がある理由は、ツールチップが表示されたらポップアップを処分しないことでパフォーマンスを最適化しようとする可能性があるためです。

アップデート

Realimageのために投稿したコードは機能するはずであり、私が考えていたものです。今朝、Sourceuriが指定されていない限り、BitMapCacheoptionまたはBitMapCreateOptionを設定する必要がないことに気付きました。これを反映するために答えを更新し、また弱いことを明確にしました。また、テンプレートのバグも修正しました。「Realimage.target」に拘束されるべきだったときに、「Relimage」に拘束されていました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top