Ho riscontrato un problema simile durante l'utilizzo di un numero elevato di WPF DataGrid
allo stesso tempo. E, infine, è sceso a due grandi temi:
- I dizionari risorse
- Attacchi
Resource Dizionari
Questi possono essere i principali colli di bottiglia se si usa di base WPF dispone senza essere attento.
Nel mio caso, per un unico rotolo logica nella ItemsControl
che è stato che contiene il mio DataGrids
, mi è stato sempre qualcosa come 10 milioni di chiamata a GetValue
e GetValueWithoutLock
su ResourceDictionary. Più di 1 secondo da elaborare.
Questo importante numero di ResourceDictionary
accessi è stato causato da diverse fonti:
- dinamica di recupero delle risorse: se si dispone
ControlTemplates
, e più in generale le risorse poste in alcuni dizionari di risorse, e li si accede tramite {DynamicResource ...}
, rimuoverli . Avere qualcosa di statico da qualche parte e accedervi direttamente.
- Recupero di stile: se non hai uno stile sul diverso Visual che usi, o se hai uno stile ma non hai impostato la proprietà FrameworkElement.OverridesDefaultStyle, WPF proverà a trovare uno stile che corrisponda al controllo in tutte le risorse, il che risulta in molti accessi ai dizionari delle risorse. Per evitare ciò, assicurarsi di ignorare tutti i modelli di controllo dei controlli e impostare
Style={x:Null}
su ogni singolo controllo (se è necessario uno stile per un controllo, impostarlo in linea sul proprio controllo e aggiungere OverridesDefaultStyle = true
)
- Implicito DataTemplates: i modelli di dati impliciti sono molto utili ma sono tutt'altro che gratuiti. Quando si cerca l'applicazione di
DataTemplate
, WPF sfoglia nuovamente i dizionari delle risorse per trovare uno DataTemplate
corrispondente ai tipi ViewModels. La soluzione consiste nell'utilizzare un selettore DataTemplate
per ogni controllo associato a un ViewModel e implementare un modo ottimizzato per recuperare il valore corretto DataTemplate
. (Personalmente ho alcuni campi statici per il mio dataTemplate che recupero solo una volta da un resourceDictionary e uno DataTemplateSelector
ottimizzato che li restituisce secondo necessità.)
Associazioni
Associazioni sono molto utili, ma molto costoso, la memoria e le prestazioni saggio saggio. In un ambiente molto sensato - dal punto di vista delle prestazioni - non puoi semplicemente usarli senza fare attenzione. Ad esempio, il binding può creare fino a 3 WeakReferences per ciascun oggetto binded, può usare reflection, ecc. Alla fine ho finito con la rimozione di quasi tutto il mio gestore di eventi binding e plugged sull'evento PropertyChanged di DataContext. Quando si modifica DataContext
sui miei controlli (si dispone di un evento DataContextChanged
), verifica se il mio DataContext
supporta INotifyPropertyChanged
e, in caso affermativo, allego un gestore di eventi nell'evento PropertyChanged
e aggiorno le proprietà in base alle esigenze. (Ho avuto solo un modo di legare, quindi è per questo che ho scelto questo modo di fare le cose, ma ci sono altre soluzioni).
Può sembrare frustrante non utilizzare i binding quando si utilizzano MVVM e WPF, ma nel mio caso non c'era alcun modo per ottimizzare i binding.
Ultima cosa: se si dispone di oggetti Freezable
(come i pennelli, ad esempio), non esitare a Freeze
se possibile.
Questi sono alcuni consigli che possono aiutare a ottimizzare il codice. Avrai bisogno di un profiler (consiglio sempre di usare dotTrace dato che questo è il miglior profiler che abbia mai usato) per monitorare ciò che sta realmente accadendo e adattarlo in base ai risultati.
Buona fortuna!
Grazie per la risposta dettagliata. Contiene già alcuni punti che posso migliorare nella mia applicazione (freezables, default style override). Controllerò questo e riferirò più tardi. –
Certo, fammi sapere come va! In realtà è stato un buon esercizio per me perché devo scrivere un post sul mio blog :) – Sisyphe
Abbiamo molti dizionari di risorse per tutto e l'applicazione è ancora molto veloce.Il modo in cui ci siamo avvicinati era creare un dizionario di risorse per una risorsa (come stile, vettore, pennello, ecc.), Quindi da ciascuna vista si fa riferimento solo a quei dizionari di risorse che sono necessari. Il problema è la griglia uniforme stessa, perché non virtualizza. – adminSoftDK