Ottimizzazione delle prestazioni: Comportamento degli oggettiOptimizing Performance: Object Behavior

La comprensione del comportamento intrinseco degli oggetti WPFWPF consente di trovare più facilmente il compromesso ideale tra funzionalità e prestazioni.Understanding the intrinsic behavior of WPFWPF objects will help you make the right tradeoffs between functionality and performance.

La mancata rimozione di gestori eventi dagli oggetti può mantenere gli oggetti attiviNot Removing Event Handlers on Objects may Keep Objects Alive

Il delegato passato da un oggetto al relativo evento è di fatto un riferimento all'oggetto.The delegate that an object passes to its event is effectively a reference to that object. I gestori eventi, quindi, possono mantenere gli oggetti attivi più a lungo del previsto.Therefore, event handlers can keep objects alive longer than expected. Quando si esegue la pulitura di un oggetto registrato per restare in ascolto di un evento dell'oggetto, è essenziale rimuovere il delegato prima di rilasciare l'oggetto.When performing clean up of an object that has registered to listen to an object's event, it is essential to remove that delegate before releasing the object. Mantenere attivi oggetti non necessari aumenta il consumo di memoria dell'applicazione,Keeping unneeded objects alive increases the application's memory usage. soprattutto se l'oggetto è la radice di un albero logico o di una struttura ad albero visuale.This is especially true when the object is the root of a logical tree or a visual tree.

In WPFWPF è stato introdotto un modello di listener di eventi debole per eventi che possono rivelarsi utili in situazioni in cui è difficile tenere traccia delle relazioni di durata degli oggetti tra l'origine e il listener.WPFWPF introduces a weak event listener pattern for events that can be useful in situations where the object lifetime relationships between source and listener are difficult to keep track of. Alcuni eventi WPFWPF esistenti usano già questo modello,Some existing WPFWPF events use this pattern. che può essere utile soprattutto per implementare oggetti con eventi personalizzati.If you are implementing objects with custom events, this pattern may be of use to you. Per informazioni dettagliate, vedere Modelli di eventi deboli.For details, see Weak Event Patterns.

Sono disponibili vari strumenti, ad esempio il profiler CLR e il visualizzatore del working set, in grado di fornire informazioni sul consumo di memoria di un determinato processo.There are several tools, such as the CLR Profiler and the Working Set Viewer, that can provides information on the memory usage of a specified process. Il profiler CLR include alcune visualizzazioni del profilo di allocazione molto utili, tra cui un istogramma dei tipi allocati, grafici delle allocazioni e delle chiamate, una cronologia delle operazioni di Garbage Collection di varie generazioni e lo stato dell'heap gestito che ne deriva e una struttura ad albero delle chiamate che mostra le allocazioni per metodo e i caricamenti degli assembly.The CLR Profiler includes a number of very useful views of the allocation profile, including a histogram of allocated types, allocation and call graphs, a time line showing garbage collections of various generations and the resulting state of the managed heap after those collections, and a call tree showing per-method allocations and assembly loads. Per altre informazioni, vedere .NET Framework Developer Center (Centro sviluppatori per .NET Framework).For more information, see .NET Framework Developer Center.

Proprietà e oggetti di dipendenzaDependency Properties and Objects

In generale, l'accesso a una proprietà di dipendenza DependencyObject di un oggetto non è più lento dell'accesso a una proprietà CLR.In general, accessing a dependency property of a DependencyObject is not slower than accessing a CLR property. Sebbene si verifichi un lieve sovraccarico delle prestazioni per l'impostazione di un valore di proprietà, il recupero di un valore è rapido quanto il recupero del valore da una proprietà CLR.While there is a small performance overhead for setting a property value, getting a value is as fast as getting the value from a CLR property. Il sovraccarico delle prestazioni, infatti, è compensato dalla capacità delle proprietà di dipendenza di supportare funzionalità avanzate come il data binding, l'animazione, l'ereditarietà e l'applicazione di stili.Offsetting the small performance overhead is the fact that dependency properties support robust features, such as data binding, animation, inheritance, and styling. Per altre informazioni, vedere Panoramica sulle proprietà di dipendenza.For more information, see Dependency Properties Overview.

Ottimizzazioni di DependencyPropertyDependencyProperty Optimizations

È necessario definire le proprietà di dipendenza nell'applicazione con estrema attenzione.You should define dependency properties in your application very carefully. Se la DependencyProperty proprietà ha effetto solo sulle opzioni dei metadati del tipo di rendering, anziché AffectsMeasuresu altre opzioni di metadati, ad esempio, è necessario contrassegnarla come tale eseguendo l'override dei relativi metadati.If your DependencyProperty affects only render type metadata options, rather than other metadata options such as AffectsMeasure, you should mark it as such by overriding its metadata. Per altre informazioni sull'override dei metadati delle proprietà o su come ottenere i metadati delle proprietà, vedere Metadati delle proprietà di dipendenza.For more information about overriding or obtaining property metadata, see Dependency Property Metadata.

Nel caso in cui non tutte le modifiche alle proprietà influiscano effettivamente sulla misura, la disposizione e il rendering, può essere più vantaggioso avere un gestore delle modifiche alle proprietà che consenta di invalidare manualmente la misura, la disposizione e i passaggi di rendering.It may be more efficient to have a property change handler invalidate the measure, arrange, and render passes manually if not all property changes actually affect measure, arrange, and render. È possibile, ad esempio, decidere di eseguire nuovamente il rendering di uno sfondo solo se un valore è superiore a un limite impostato.For instance, you might decide to re-render a background only when a value is greater than a set limit. In questo caso, il rendering verrebbe invalidato dal gestore delle modifiche alle proprietà solo se il valore supera il limite impostato.In this case, your property change handler would only invalidate render when the value exceeds the set limit.

Problemi legati alla possibilità di rendere ereditabile un oggetto DependencyPropertyMaking a DependencyProperty Inheritable is Not Free

Per impostazione predefinita, le proprietà di dipendenza registrate non sono ereditabili.By default, registered dependency properties are non-inheritable. È possibile tuttavia rendere ereditabile qualsiasi proprietà in modo esplicito.However, you can explicitly make any property inheritable. Sebbene possa essere utile, la conversione di una proprietà per renderla ereditabile incide sulle prestazioni, poiché aumenta la durata della procedura di annullamento della convalida della proprietà.While this is a useful feature, converting a property to be inheritable impacts performance by increasing the length of time for property invalidation.

Uso corretto di RegisterClassHandlerUse RegisterClassHandler Carefully

Quando la RegisterClassHandler chiamata a consente di salvare lo stato dell'istanza, è importante tenere presente che il gestore viene chiamato su ogni istanza, che può causare problemi di prestazioni.While calling RegisterClassHandler allows you to save your instance state, it is important to be aware that the handler is called on every instance, which can cause performance problems. Usare RegisterClassHandler solo quando l'applicazione richiede di salvare lo stato dell'istanza.Only use RegisterClassHandler when your application requires that you save your instance state.

Impostazione del valore predefinito di un oggetto DependencyProperty durante le registrazioneSet the Default Value for a DependencyProperty during Registration

Quando DependencyProperty sicreaunoggettoDependencyPropertyche richiede un valore predefinito, impostare il valore utilizzando i metadati predefiniti passati come parametro al metododi.RegisterWhen creating a DependencyProperty that requires a default value, set the value using the default metadata passed as a parameter to the Register method of the DependencyProperty. Usare questa tecnica, anziché impostare il valore della proprietà, in un costruttore o in ogni istanza di un elemento.Use this technique rather than setting the property value in a constructor or on each instance of an element.

Impostazione del valore PropertyMetadata usando RegisterSet the PropertyMetadata Value using Register

Quando si crea DependencyPropertyun oggetto, è possibile PropertyMetadata impostare utilizzando Register il metodo o OverrideMetadata .When creating a DependencyProperty, you have the option of setting the PropertyMetadata using either the Register or OverrideMetadata methods. Sebbene l'oggetto possa avere un costruttore statico da chiamare OverrideMetadata, questa non è la soluzione ottimale e avrà un effetto sulle prestazioni.Although your object could have a static constructor to call OverrideMetadata, this is not the optimal solution and will impact performance. Per ottenere prestazioni ottimali, PropertyMetadata impostare l'oggetto durante Registerla chiamata a.For best performance, set the PropertyMetadata during the call to Register.

Oggetti FreezableFreezable Objects

Un Freezable è un tipo speciale di oggetto con due stati: non bloccato e bloccato.A Freezable is a special type of object that has two states: unfrozen and frozen. Bloccare gli oggetti ogni volta che è possibile migliora le prestazioni dell'applicazione e ne riduce il working set.Freezing objects whenever possible improves the performance of your application and reduces its working set. Per altre informazioni, vedere Cenni preliminari sugli oggetti Freezable.For more information, see Freezable Objects Overview.

Ogni Freezable oggetto ha Changed un evento che viene generato ogni volta che viene modificato.Each Freezable has a Changed event that is raised whenever it changes. Le notifiche di modifica, tuttavia, sono molto dispendiose in termini di prestazioni dell'applicazione.However, change notifications are costly in terms of application performance.

Si consideri l'esempio seguente Rectangle in cui ogni Brush utilizza lo stesso oggetto:Consider the following example in which each Rectangle uses the same Brush object:

rectangle_1.Fill = myBrush;
rectangle_2.Fill = myBrush;
rectangle_3.Fill = myBrush;
// ...
rectangle_10.Fill = myBrush;
rectangle_1.Fill = myBrush
rectangle_2.Fill = myBrush
rectangle_3.Fill = myBrush
' ...
rectangle_10.Fill = myBrush

Per impostazione predefinita WPFWPF , fornisce un gestore eventi per SolidColorBrush l' Changed evento dell'oggetto per invalidare la Fill proprietà Rectangle dell'oggetto.By default, WPFWPF provides an event handler for the SolidColorBrush object's Changed event in order to invalidate the Rectangle object's Fill property. In questo caso, ogni volta SolidColorBrush che deve Changed generare l'evento, è necessario richiamare la funzione di callback per ogni Rectangle, ovvero l'accumulo di queste chiamate di funzione di callback impone una riduzione significativa delle prestazioni.In this case, each time the SolidColorBrush has to fire its Changed event it is required to invoke the callback function for each Rectangle—the accumulation of these callback function invocations impose a significant performance penalty. Ma non solo: per aggiungere e rimuovere gestori in questa fase, l'applicazione deve scorrere tutto l'elenco, con un considerevole dispendio di prestazioni.In addition, it is very performance intensive to add and remove handlers at this point since the application would have to traverse the entire list to do so. Se lo SolidColorBrushscenario dell'applicazione non modifica mai, si pagherà il costo della gestione Changed inutilmente dei gestori eventi.If your application scenario never changes the SolidColorBrush, you will be paying the cost of maintaining Changed event handlers unnecessarily.

Il blocco Freezable di un può migliorare le prestazioni, perché non è più necessario spendere risorse per la gestione delle notifiche di modifica.Freezing a Freezable can improve its performance, because it no longer needs to expend resources on maintaining change notifications. La tabella seguente mostra le dimensioni di una semplice SolidColorBrush quando la IsFrozen relativa proprietà è impostata truesu, rispetto a quando non lo è.The table below shows the size of a simple SolidColorBrush when its IsFrozen property is set to true, compared to when it is not. In questo modo si presuppone l' Fill applicazione di un pennello alla proprietà di dieci Rectangle oggetti.This assumes applying one brush to the Fill property of ten Rectangle objects.

StatoState DimensioneSize
BloccatoSolidColorBrushFrozen SolidColorBrush 212 byte212 Bytes
Non bloccatoSolidColorBrushNon-frozen SolidColorBrush 972 byte972 Bytes

Nell'esempio di codice seguente viene dimostrato questo concetto:The following code sample demonstrates this concept:

Brush frozenBrush = new SolidColorBrush(Colors.Blue);
frozenBrush.Freeze();
Brush nonFrozenBrush = new SolidColorBrush(Colors.Blue);

for (int i = 0; i < 10; i++)
{
    // Create a Rectangle using a non-frozed Brush.
    Rectangle rectangleNonFrozen = new Rectangle();
    rectangleNonFrozen.Fill = nonFrozenBrush;

    // Create a Rectangle using a frozed Brush.
    Rectangle rectangleFrozen = new Rectangle();
    rectangleFrozen.Fill = frozenBrush;
}
Dim frozenBrush As Brush = New SolidColorBrush(Colors.Blue)
frozenBrush.Freeze()
Dim nonFrozenBrush As Brush = New SolidColorBrush(Colors.Blue)

For i As Integer = 0 To 9
    ' Create a Rectangle using a non-frozed Brush.
    Dim rectangleNonFrozen As New Rectangle()
    rectangleNonFrozen.Fill = nonFrozenBrush

    ' Create a Rectangle using a frozed Brush.
    Dim rectangleFrozen As New Rectangle()
    rectangleFrozen.Fill = frozenBrush
Next i

Gestori modificati su oggetti Freezable non bloccati possono mantenere gli oggetti attiviChanged Handlers on Unfrozen Freezables may Keep Objects Alive

Il delegato passato da un oggetto a un Freezable Changed evento di un oggetto è in effetti un riferimento a tale oggetto.The delegate that an object passes to a Freezable object's Changed event is effectively a reference to that object. I gestori di eventi possono pertanto mantengono gli oggetti attivi più a lungo del previsto. ChangedTherefore, Changed event handlers can keep objects alive longer than expected. Quando si esegue la pulizia di un oggetto registrato per restare in attesa dell' Freezable Changed evento di un oggetto, è essenziale rimuovere il delegato prima di rilasciare l'oggetto.When performing clean up of an object that has registered to listen to a Freezable object's Changed event, it is essential to remove that delegate before releasing the object.

WPFWPFassocia Changed anche gli eventi internamente.also hooks up Changed events internally. Ad esempio, tutte le proprietà di dipendenza Freezable che accettano come valore Changed ascolteranno automaticamente gli eventi.For example, all dependency properties which take Freezable as a value will listen to Changed events automatically. La Fill proprietà, che accetta un Brushoggetto, illustra questo concetto.The Fill property, which takes a Brush, illustrates this concept.

Brush myBrush = new SolidColorBrush(Colors.Red);
Rectangle myRectangle = new Rectangle();
myRectangle.Fill = myBrush;
Dim myBrush As Brush = New SolidColorBrush(Colors.Red)
Dim myRectangle As New Rectangle()
myRectangle.Fill = myBrush

Nell' myBrush assegnazione di Changed a myRectangle.Fillun Rectangle delegato che fa riferimento all'oggetto verrà aggiunto all' SolidColorBrush evento dell'oggetto.On the assignment of myBrush to myRectangle.Fill, a delegate pointing back to the Rectangle object will be added to the SolidColorBrush object's Changed event. Nel codice seguente, quindi, myRect non viene reso idoneo per operazioni di Garbage Collection:This means the following code does not actually make myRect eligible for garbage collection:

myRectangle = null;
myRectangle = Nothing

In questo caso myBrush myRectangle continuerà a essere attivo e verrà richiamato quando viene generato l' Changed evento.In this case myBrush is still keeping myRectangle alive and will call back to it when it fires its Changed event. Si noti che assegnando myBrush Fill alla proprietà di un nuovo Rectangle è sufficiente aggiungere un altro gestore eventi myBrusha.Note that assigning myBrush to the Fill property of a new Rectangle will simply add another event handler to myBrush.

Il metodo consigliato per pulire questi tipi di oggetti consiste nel rimuovere Brush Fill dalla proprietà, che a sua volta rimuoverà il Changed gestore eventi.The recommended way to clean up these types of objects is to remove the Brush from the Fill property, which will in turn remove the Changed event handler.

myRectangle.Fill = null;
myRectangle = null;
myRectangle.Fill = Nothing
myRectangle = Nothing

Virtualizzazione dell'interfaccia utenteUser Interface Virtualization

WPFWPFfornisce inoltre una variante dell'elemento StackPanel che "virtualizza" automaticamente il contenuto figlio associato a dati.also provides a variation of the StackPanel element that automatically "virtualizes" data-bound child content. In questo contesto il termine virtualizzare si riferisce a una tecnica grazie alla quale, a partire da un numero più elevato di elementi dati, viene generato un subset di oggetti in base agli elementi visibili sullo schermo.In this context, the word virtualize refers to a technique by which a subset of objects are generated from a larger number of data items based upon which items are visible on-screen. La generazione di un elevato numero di elementi dell'interfaccia utente, quando solo alcuni possono essere visualizzati sullo schermo in un momento specifico, richiede un consumo intensivo di risorse in termini sia di memoria sia di processore.It is intensive, both in terms of memory and processor, to generate a large number of UI elements when only a few may be on the screen at a given time. VirtualizingStackPanel(tramite la ItemContainerGenerator funzionalità fornita VirtualizingPanelda) calcola gli elementi visibili e ListBox utilizza da un oggetto ItemsControl (ad esempio o ListView) per creare solo elementi per gli elementi visibili.VirtualizingStackPanel (through functionality provided by VirtualizingPanel) calculates visible items and works with the ItemContainerGenerator from an ItemsControl (such as ListBox or ListView) to only create elements for visible items.

Per ottimizzare le prestazioni, gli oggetti visivi per questi elementi vengono generati o mantenuti attivi solo se sono visibili sullo schermo.As a performance optimization, visual objects for these items are only generated or kept alive if they are visible on the screen. Quando non si trovano più nell'area visualizzabile del controllo, gli oggetti visibili possono essere rimossi.When they are no longer in the viewable area of the control, the visual objects may be removed. Questa operazione non deve essere confusa con la virtualizzazione dei dati, in cui gli oggetti dati non sono tutti presenti nella raccolta locale, ma trasmessi a seconda delle esigenze.This is not to be confused with data virtualization, where data objects are not all present in the local collection- rather streamed in as needed.

La tabella seguente mostra il tempo trascorso per l'aggiunta e il TextBlock rendering degli elementi StackPanel 5000 in VirtualizingStackPanelun oggetto e un oggetto.The table below shows the elapsed time adding and rendering 5000 TextBlock elements to a StackPanel and a VirtualizingStackPanel. In questo scenario, le misurazioni rappresentano il tempo che intercorre tra la connessione di ItemsSource una stringa di ItemsControl testo alla proprietà di un oggetto e l'ora in cui gli elementi del pannello visualizzano la stringa di testo.In this scenario, the measurements represent the time between attaching a text string to the ItemsSource property of an ItemsControl object to the time when the panel elements display the text string.

Pannello hostHost panel Tempo di rendering (ms)Render time (ms)
StackPanel 32103210
VirtualizingStackPanel 4646

Vedere ancheSee also