/ / Perdita di memoria WPF - .net, wpf, performance, perdite di memoria

Perdita di memoria WPF - .net, wpf, prestazioni, perdite di memoria

Ho un modulo WPF che io stesso non ho creato, quindi non sono molto bravo in WPF. Sta perdendo molto però, fino a 400 MB e la chiusura del modulo non aiuta.

Il problema risiede nella mia applicazione che carica tuttole foto in una volta. Vorrei caricare solo quelli visibili al momento. Sono circa 300 immagini e sono un po 'grandi, quindi il mio modulo WPF soffre di caricarle tutte.

Ho un DataTemplate con il mio tipo che ha una proprietà Thumbnail. Il codice nel modello è così:

            <Image Source="{Binding Path=Thumbnail}" Stretch="Fill"/>

E poi ho una griglia con un controllo che hail modello sopra come fonte. Il codice per questo controllo è il seguente. Per favore, forniscimi consigli su come ottimizzare il codice e forse ottenere gli unici che sono visibili e che sono caricati solo molti controlli contemporaneamente?

    <Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Controls:ElementFlow">
<Grid Background="{TemplateBinding Background}">
<Canvas x:Name="PART_HiddenPanel"
IsItemsHost="True"
Visibility="Hidden" />
<Viewport3D x:Name="PART_Viewport">
<!-- Camera -->
<Viewport3D.Camera>
<PerspectiveCamera FieldOfView="60"
Position="0,1,4"
LookDirection="0,-1,-4"
UpDirection="0,1,0" />
</Viewport3D.Camera>

<ContainerUIElement3D x:Name="PART_ModelContainer" />

<ModelVisual3D>
<ModelVisual3D.Content>
<AmbientLight Color="White" />
</ModelVisual3D.Content>
</ModelVisual3D>
<Viewport2DVisual3D
RenderOptions.CachingHint="Cache"
RenderOptions.CacheInvalidationThresholdMaximum="2"
RenderOptions.CacheInvalidationThresholdMinimum="0.5"/>
</Viewport3D>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

risposte:

2 per risposta № 1

Il controllo "ElementFlow" è lo stesso descritto? Qui? Sembra che il controllo sia già utilizzando la virtualizzazione, quindi non mi aspetto che acceda alla proprietà Miniatura di un elemento non visibile.

Come stai modellando la struttura dei dati cheespone la proprietà "Miniatura"? Puoi impostarlo in modo tale che la proprietà carichi la miniatura al primo accesso? Forse implementarlo con una cache di supporto (che mantiene le anteprime caricate per un certo periodo di tempo) risolverà il problema.

MODIFICARE

Potrei aver supposto qualcosa che non avrei dovuto. Nel leggere i commenti al secondo post che ho collegato, ora penso che potrebbe essere che la versione pubblicamente disponibile del controllo ElementFlow non implementa, di fatto, la virtualizzazione. Forse potresti accedere alla proprietà "Miniatura" e determinare se si accede alla proprietà per elementi non visibili.


4 per risposta № 2

Il primo posto da guardare quando si cerca di trovare perdite di memoria in un'applicazione .NET, WPF o meno, sono gli oggetti che si iscrivono agli eventi.

Se l'oggetto X sta ascoltando un evento generato dal'oggetto Y, quindi Y contiene un riferimento a X. Qualunque sia il metodo di virtualizzazione (o eliminazione) implementato, se X non annulla l'iscrizione all'evento di Y, X rimarrà nel grafico dell'oggetto fino a quando lo fa Y e non otterrà mai finalizzato e raccolto. (Anche se implementa IDisposable e tu chiami esplicitamente Dispose su di essa.)

Quando dici "chiudere il modulo non aiuta", ciò mi rende doppiamente sospetto: mi aspetto che qualcuno abbia implementato una proprietà dell'oggetto sul Window oggetto e quell'oggetto si è abbonato a un evento di qualche tipo. Quindi chiudi la finestra, ma esiste ancora nel grafico dell'oggetto perché viene fatto riferimento a una delle sue proprietà.

(Per darti un'idea di quanto possa essere insidioso questo: WinForms ToolStrip controlla la sottoscrizione agli eventi di modifica del tema di Windowsquando diventano visibili. Questo è fantastico in quanto cambiare il tema del tuo computer si riflette automagicamente sull'interfaccia utente dell'applicazione in esecuzione. Non è così eccezionale se si dereference un ToolStrip senza prima impostazione Visible su false, continuerà a ricevere eventi di modifica del tema fino al termine dell'applicazione.)

Un profiler di memoria può aiutare in questo - ecco come ho scoperto che la mia applicazione ne aveva migliaia ToolStrip oggetti in memoria anche se pensavo che fossero stati tutti distrutti.


0 per risposta № 3

È difficile restringere il problema solo con lo snippet di codice. Potresti volere Visual Profiler se non lo hai già fatto.