Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A WPF-objektumok belső viselkedésének megértése segít a funkciók és a teljesítmény közötti megfelelő kompromisszumokban.
Az objektumok eseménykezelőinek eltávolítása életben tarthatja az objektumokat
Az a delegálás, amelyet egy objektum átad az eseménynek, valójában az adott objektumra mutató hivatkozás. Ezért az eseménykezelők a vártnál tovább életben tarthatják az objektumokat. Amikor egy objektum eseményének figyeléséhez regisztrált objektum megtisztítását végzi, az objektum felszabadítása előtt el kell távolítania a delegáltat. A szükségtelen objektumok életben tartása növeli az alkalmazás memóriahasználatát. Ez különösen igaz, ha az objektum gyökere egy logikai vagy vizuális fa.
A WPF gyenge eseményfigyelő mintát vezet be az olyan eseményekhez, amelyek hasznosak lehetnek olyan helyzetekben, amikor a forrás és a figyelő közötti objektumélettartam-kapcsolatok nehezen követhetők nyomon. Néhány meglévő WPF-esemény ezt a mintát használja. Ha egyéni eseményekkel rendelkező objektumokat implementál, ez a minta hasznos lehet Önnek. További részletekért lásd a Gyenge eseményminták című témakört.
Számos olyan eszköz létezik, például a CLR Profiler és a Munkakészlet-megjelenítő, amelyek információt nyújtanak egy adott folyamat memóriahasználatáról. A CLR Profiler számos nagyon hasznos nézetet tartalmaz a foglalási profilról, beleértve a lefoglalt típusok hisztogramját, a foglalási és hívási grafikonokat, a különböző generációk szemétgyűjteményeit és a gyűjtemények utáni felügyelt halom eredményül kapott állapotát megjelenítő idősort, valamint egy metódusonkénti foglalásokat és szerelvényterheléseket megjelenítő hívásfát. További információ: Teljesítmény.
Függőségi tulajdonságok és objektumok
A függőségi tulajdonság DependencyObject elérése általában nem lassabb, mint egy CLR-tulajdonság elérése. Bár a tulajdonságértékek beállításának kisebb teljesítményterhelése van, az érték lekérése ugyanolyan gyors, mint egy CLR-tulajdonságból származó érték lekérése. A kis teljesítményterhelés ellensúlyozása az a tény, hogy a függőségi tulajdonságok támogatják a robusztus funkciókat, például az adatkötést, az animációt, az öröklést és a stílust. További információ: Függőség tulajdonságainak áttekintése.
DependencyProperty optimalizálások
Nagyon körültekintően kell meghatároznia a függőségi tulajdonságokat az alkalmazásban. Ha a DependencyProperty csak a megjelenítési típusú metaadat-beállításokat érinti, és nem más metaadat-beállításokat, mint például a AffectsMeasure, akkor a metaadatok felülírásával kell megjelölnie. A tulajdonság metaadatainak felülkéréséről vagy lekéréséről további információt a Függőségi tulajdonság metaadatai című témakörben talál.
Hatékonyabb lehet, ha egy tulajdonságváltozás-kezelő manuálisan érvényteleníti a mérési, elrendezési és renderelési folyamatokat, amennyiben nem minden tulajdonságmódosítás befolyásolja ezeket ténylegesen. Előfordulhat például, hogy csak akkor jelenít meg újra egy hátteret, ha egy érték nagyobb a megadott korlátnál. Ebben az esetben a tulajdonságváltozás-kezelő csak akkor érvényteleníti a renderelést, ha az érték meghaladja a beállított korlátot.
A DependencyProperty Örökölhetővé tétele nem ingyenes
Alapértelmezés szerint a regisztrált függőségi tulajdonságok nem örökölhetők. Azonban bármely tulajdonságot explicit módon örökölhetővé tehet. Bár ez hasznos funkció, a tulajdonságok örökölhetővé alakítása hatással van a teljesítményre azáltal, hogy növeli a tulajdonság érvénytelenítésének időtartamát.
A RegisterClassHandler körültekintő használata
Miközben a hívással RegisterClassHandler mentheti a példány állapotát, fontos tisztában lenni azzal, hogy a kezelő minden példányon meghívva van, ami teljesítményproblémát okozhat. Csak akkor használja RegisterClassHandler , ha az alkalmazás megköveteli a példány állapotának mentését.
A DependencyProperty alapértelmezett értékének beállítása a regisztráció során
Egy DependencyProperty létrehozásakor, amely alapértelmezett értéket igényel, állítsa be az értéket az alapértelmezett metadaták használatával, amelyeket paraméterként ad át a Register metódusnak a DependencyProperty. Ezt a technikát használja ahelyett, hogy a tulajdonságértéket konstruktorban vagy egy elem minden példányán beállítanák.
A PropertyMetadata érték beállítása a regisztrációval
A DependencyProperty létrehozása során lehetősége van beállítani a PropertyMetadata paramétert a Register vagy a OverrideMetadata metódusok használatával. Bár az objektumnak statikus konstruktort kell meghívnia OverrideMetadata, ez nem az optimális megoldás, és hatással lesz a teljesítményre. A legjobb teljesítmény érdekében állítsa be a PropertyMetadata-t a hívás közben Register.
Fagyasztható objektumok
A Freezable egy speciális objektumtípus, amelynek két állapota van: unfrozen és frozen. Ha lehetséges, az objektumok befagyasztása javítja az alkalmazás teljesítményét, és csökkenti annak munkakészletét. További információ: Fagyasztható objektumok áttekintése.
Mindegyiknek Freezable van egy Changed eseménye, amely akkor jön létre, amikor megváltozik. A változásértesítések azonban az alkalmazás teljesítménye szempontjából költségesek.
Vegye figyelembe az alábbi példát, amelyben mindegyik Rectangle ugyanazt Brush az objektumot használja:
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
A WPF alapértelmezés szerint biztosít egy eseménykezelőt az SolidColorBrush objektum Changed eseményéhez, hogy érvénytelenítse a Rectangle objektum Fill tulajdonságát. Ebben az esetben minden alkalommal, amikor a `SolidColorBrush` esemény bekövetkezik, meg kell hívnia a callback függvényt mindegyik `Changed` esetén – ezeknek a callback függvény-hívásoknak a felhalmozása jelentős teljesítménycsökkenést okoz. Emellett ezen a ponton nagyon nagy teljesítményigényű kezelők hozzáadása és eltávolítása, mivel ehhez az alkalmazásnak végig kell haladnia a teljes listán. Ha az alkalmazásforgatókönyv soha nem változtatja meg a SolidColorBrush, akkor az eseménykezelők szükségtelen karbantartásának költségeit fogja fizetni.
A Freezable befagyasztás javíthatja a teljesítményét, mivel többé nem kell erőforrásokat kiutasítania a változásértesítések fenntartásához. Az alábbi táblázat egy egyszerű SolidColorBrush méretét mutatja, amikor a IsFrozen tulajdonsága true-re van állítva, összehasonlítva azzal, amikor nincs beállítva. Ez azt feltételezi, hogy egy ecsetet alkalmaznak a Fill tulajdonságára tíz Rectangle objektumnak.
| Állam | Méret |
|---|---|
| Fagyott SolidColorBrush | 212 bájt |
| Nem fagyasztott SolidColorBrush | 972 bájt |
A következő kódminta ezt a fogalmat mutatja be:
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
A nem fagyasztható objektumok módosított kezelői életben tarthatják az objektumokat
Az a delegálás, amelyet egy objektum átad egy Freezable objektum eseményének Changed , valójában az adott objektumra mutató hivatkozás. Ezért az Changed eseménykezelők a vártnál tovább életben tarthatják az objektumokat. Amikor egy objektum, amely egy Freezable objektum Changed eseményének figyelésére regisztrált, megtisztításra kerül, lényeges, hogy az objektum felszabadítása előtt eltávolítsa azt a delegáltat.
A WPF belsőleg is összekapcsolja Changed az eseményeket. Például minden olyan függőségi tulajdonság, amely értéket vesz fel Freezable , automatikusan figyeli az Changed eseményeket. A Fill tulajdonság, amely egy Brush, szemlélteti ezt a fogalmat.
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
A myBrushmyRectangle.Fill hozzárendelésekor egy, az Rectangle objektumra mutató delegált lesz hozzáadva az SolidColorBrush eseményhez az Changed objektumra. Ez azt jelenti, hogy a következő kód valójában nem teszi myRect-t jogosulttá a szemétgyűjtésre.
myRectangle = null;
myRectangle = Nothing
Ebben az esetben myBrush továbbra is életben tartja myRectangle, és vissza fogja hívni, amikor bekövetkezik az Changed esemény. Vegye figyelembe, hogy a myBrush hozzárendelése egy új Fill tulajdonsághoz egyszerűen hozzáad egy másik eseménykezelőt a Rectangle-hez.
Az ilyen típusú objektumok eltávolításának ajánlott módja a Brush tulajdonság eltávolítása Fill , amely eltávolítja az eseménykezelőt Changed .
myRectangle.Fill = null;
myRectangle = null;
myRectangle.Fill = Nothing
myRectangle = Nothing
Felhasználói felület virtualizálása
A WPF az StackPanel elem egy olyan változatát is biztosítja, amely automatikusan "virtualizálja" az adatokhoz kötött gyermektartalmat. Ebben az összefüggésben a virtualizálás szó egy olyan technikára utal, amellyel az objektumok egy részhalmaza nagyobb számú adatelemből jön létre, amelyek alapján az elemek láthatók a képernyőn. A memória és a processzor szempontjából is nagy mennyiségű felhasználói felületi elem létrehozása szükséges, ha egy adott időpontban csak néhány lehet a képernyőn. VirtualizingStackPanel (a VirtualizingPanel által nyújtott funkciókkal) kiszámolja a látható elemeket, és a ItemContainerGenerator egy ItemsControl-ját (például ListBox vagy ListView) használva csak a látható elemekhez hoz létre elemeket.
Teljesítményoptimalizálásként az elemek vizuális objektumai csak akkor jönnek létre vagy maradnak életben, ha láthatók a képernyőn. Ha már nincsenek a vezérlő megjeleníthető területén, a vizualizációs objektumok eltávolíthatók. Ez nem tévesztendő össze az adatvirtualizálással, ahol az adatobjektumok nem mind jelennek meg a helyi gyűjteményben, hanem szükség szerint folyamatosan beérkeznek.
Az alábbi táblázat azt mutatja, mennyi idő telt el 5000 TextBlock elem hozzáadásával és megjelenítésével egy StackPanel és egy VirtualizingStackPanel esetén. Ebben a forgatókönyvben a mérések azt az időt jelölik, amikor egy szöveges sztringet ItemsSource egy objektum tulajdonságához ItemsControl csatolnak ahhoz az időponthoz, amikor a panel elemei megjelenítik a szöveges sztringet.
| Kiszolgáló panel | renderelési idő (ms) |
|---|---|
| StackPanel | 3210 |
| VirtualizingStackPanel | 46 |
Lásd még
.NET Desktop feedback