Pergunta

Desenvolvi um aplicativo para capturar e salvar imagens em um banco de dados, mas estou tendo um problema com o uso da memória. No meu objeto de domínio, tenho 3 propriedades:

Imagem - Array de bytes, o conteúdo é um JPG

RealImagethumb - A matriz de bytes convertida em um bitmapimage e encolheu, exibida ao usuário em uma Gridview com outras miniaturas

Realimage - não possui Setter, a matriz de bytes convertida em uma fonte de bitmap, isso é mostrado em uma dica de ferramenta quando o usuário paira sobre ela.

O problema que tenho é que, se um usuário pairar sobre cada imagem, por sua vez, o uso da memória espiral. Sei que, à medida que um usuário paira sobre fontes de bitmap é gerado e a memória não é liberada, tentei dar à Realimage uma propriedade de apoio e atribuí -lo a nulo depois, mas novamente a memória não é liberada (esperando o lixo colecionador?).

editar:

É isso que você quis dizer Ray? Não estou recebendo nada mostrado na dica de ferramenta como abaixo, mas se eu tentar definir um WeakReference<BitmapImage>, Eu recebo o sistema.WeakReference não possui erro de parâmetros de tipo.

  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;
            }
        }
Foi útil?

Solução

Você precisará fazer três coisas:

  1. Ao construir seu bitmapimage, use o STreamSource para fornecer os dados. Não use o Urisource ou passe um URI para o construtor, o que faria com que a imagem fosse adicionada ao cache da imagem.

  2. Na implementação do Realimage do seu objeto de domínio, armazene uma referência fraca para o seu bitmapimage, e não o próprio bitmapimage. Quando o RealImage for buscado, se a referência fraca ou a referência fraca. O alvo for nulo, crie um novo bitmapimage e uma nova referência fraca.

  3. Use um datatrigger com troca de modelo para incluir apenas seu controle de imagem na árvore visual quando estiver visível

Aqui estão os modelos necessários para a Etapa 3, incluindo o do Datatrigger:

<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>

Agora você pode definir sua dica de ferramenta assim:

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

Como funciona: existem dois conteúdo de propresentadores dentro um do outro:

  • Quando o excesso de conteúdo externo é invisível, o conteúdo interno do PRESENTRENTER terá o vazio, para que nenhuma imagem seja carregada.
  • Quando o excesso de conteúdo externo estiver visível, o interior do conteúdo do RealImageTemplate para que a imagem seja carregada e exibida.

O motivo pelo qual você precisa fazer isso é que uma dica de ferramenta pode tentar otimizar o desempenho por não descartar o pop -up depois de ser mostrado.

Atualizar

O código que você postou para o Realimage deve trabalhar e é quase exatamente o que eu estava pensando. Percebi que esta manhã não há realmente necessidade de definir o BitmapCacheOption ou o BitmapCreateOption, desde que nenhum fonte seja especificado. Atualizei minha resposta para refletir isso e também para esclarecer a coisa da referência fraca. Também corrigi um bug no modelo: eu estava vinculando ao "Realimage" quando deveria estar vinculado ao "realimage.Target".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top