Visualizzazione Immagine da array di byte in WPF - Problemi di memoria
-
27-09-2019 - |
Domanda
ho sviluppato un'applicazione per catturare e salvare le immagini in un database, ma sto avendo un problema con l'utilizzo di memoria. Sul mio oggetto di dominio Ho 3 proprietà:
Immagine - matrice Byte, i contenuti sono un jpg
RealImageThumb - L'array di byte convertito in una BitmapImage e ristretto, visualizzato all'utente in un GridView con altre miniature
RealImage -. Non ha setter, l'array di byte convertito ad una sorgente bitmap, questo è mostrato in un suggerimento quando le si adagia su di esso utente
Il problema che ho è che se un utente passa sopra ogni immagine a sua volta spirali utilizzo della memoria. Mi rendo conto che come un utente si posiziona su fonti bitmap sono generati e la memoria non viene liberata, ho provato dando RealImage una struttura di supporto e l'assegnazione di questa NULL dopo ma ancora la memoria non viene liberata (attesa per la spazzatura collezionista?).
modifica:
E 'questo quello che volevi dire Ray? Non ricevo tutto quanto riportato nella descrizione come sotto, ma se provo e definire un WeakReference<BitmapImage>
, ottengo lo System.WeakReference non avere errore di parametri di 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;
}
}
Soluzione
Si avrà bisogno di fare tre cose:
-
Nel costruire il vostro BitmapImage utilizzo StreamSource di fornire i dati. Non utilizzare UriSource o passare un Uri al costruttore, che causerebbe l'immagine da aggiungere alla cache immagine.
-
In attuazione RealImage del vostro oggetto di dominio, memorizzare un WeakReference al BitmapImage non il BitmapImage stesso. Quando RealImage è inverosimile, se uno o WeakReference WeakReference.Target è nullo, creare un nuovo BitmapImage e un nuovo WeakReference ad esso.
-
Usa un DataTrigger con commutazione template per includere solo il vostro controllo Image nella struttura ad albero visuale quando è visibile
Ecco i modelli necessari per la fase 3, tra cui quello con la 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>
Ora è possibile definire la descrizione comandi in questo modo:
<Rectangle Width="40" Height="40" Fill="Blue">
<Rectangle.ToolTip>
<ContentPresenter Content="{Binding}"
ContentTemplate="{StaticResource RealImageWhenVisible}" />
</Rectangle.ToolTip>
</Rectangle>
Come funziona: Ci sono due ContentPresenters uno dentro l'altro:
- Quando il ContentPresenter esterno è invisibile, il ContentPresenter interno avrà EmptyTemplate quindi nessuna immagine verrà caricata.
- Quando il ContentPresenter esterno è visibile, il ContentPresenter interno avrà RealImageTemplate modo l'immagine viene caricato e visualizzato.
Il motivo è necessario per fare questo è che una descrizione comandi può tentare di ottimizzare le prestazioni, non disponendo del popup una volta che è stato dimostrato.
Aggiorna
Il codice che avete inviato per RealImage dovrebbe funzionare, ed è quasi esattamente quello che stavo pensando. Mi sono reso conto di questa mattina non c'è davvero alcun bisogno di impostare BitmapCacheOption o BitmapCreateOption finché non viene specificato alcun SourceUri. Ho aggiornato la mia risposta per riflettere questa e anche per chiarire la cosa WeakReference. Ho anche corretto un bug nel modello: sono stato il legame con "RealImage" quando avrei dovuto essere vincolanti per "RealImage.Target"
.