Megosztás a következőn keresztül:


A fagyasztható objektumok áttekintése

Ez a témakör azt ismerteti, hogyan lehet hatékonyan használni és létrehozni Freezable objektumokat, amelyek olyan speciális funkciókat biztosítanak, amelyek segíthetnek az alkalmazások teljesítményének javításában. Fagyasztható objektumok például a kefék, írószerek, átalakítások, geometriák és animációk.

Mi az a fagyasztható dolog?

A Freezable egy speciális objektumtípus, amelynek két állapota van: unfrozen és frozen. A feloldáskor úgy tűnik, hogy egy Freezable úgy viselkedik, mint bármely más objektum. Fagyasztáskor a Freezable már nem módosítható.

A Freezable egy Changed eseményt biztosít, amely értesíti a megfigyelőket az objektum módosításairól. A Freezable befagyasztása javíthatja a teljesítményét, mivel már nem kell erőforrásokat költenie a változásértesítésekre. A fagyasztott Freezable a szálak között is megosztható, míg a nem fagyott Freezable nem.

Bár a Freezable osztály számos alkalmazással rendelkezik, a Windows Presentation Foundation (WPF) legtöbb Freezable objektuma a grafikus alrendszerhez kapcsolódik.

A Freezable osztály megkönnyíti bizonyos grafikus rendszerobjektumok használatát, és javíthatja az alkalmazás teljesítményét. A Freezable öröklő típusok közé tartoznak például a Brush, Transformés Geometry osztályok. Mivel nem felügyelt erőforrásokat tartalmaznak, a rendszernek módosítania kell ezeket az objektumokat, majd frissítenie kell a megfelelő nem felügyelt erőforrásokat az eredeti objektum módosításakor. Még ha nem is módosítja a grafikus rendszer objektumait, a rendszernek továbbra is az objektum figyelésére kell fordítania egyes erőforrásait, ha mégis módosítja.

Tegyük fel például, hogy létrehoz egy SolidColorBrush ecsetet, és egy gomb hátterének festésére használja.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush

A gomb megjelenítésekor a WPF grafikus alrendszer a megadott információk alapján képpontok egy csoportját festi egy gomb megjelenésének létrehozásához. Bár egyszínű kefével írta le, hogyan kell festeni a gombot, az egyszínű kefe valójában nem teszi meg a festést. A grafikus rendszer gyors, alacsony szintű objektumokat hoz létre a gombhoz és az ecsethez, és ezek azok az objektumok, amelyek ténylegesen megjelennek a képernyőn.

Ha módosítaná az ecsetet, azokat az alacsony szintű objektumokat újra kellene létrehozni. A "fagyasztható" osztály az, ami lehetővé teszi az ecset számára, hogy megtalálja a hozzá tartozó generált, alacsony szintű objektumokat, és frissítse ezeket, amikor változik. Ha ez a képesség engedélyezve van, a kefe "felolvadtnak" van mondva.

A Freezable Freeze eljárása lehetővé teszi, hogy letiltsuk az önfrissítési képességet. Ezzel a módszerrel az ecsetet "lefagyasztottá", vagy nem módosíthatóvá teheti.

Megjegyzés:

Nem minden fagyasztható objektum fagyasztható. Ha nem szeretne InvalidOperationExceptiondobni, ellenőrizze a fagyasztható objektum CanFreeze tulajdonságának értékét, és állapítsa meg, hogy le lehet-e fagyasztani, mielőtt megkísérelné lefagyasztani.

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

Ha már nem kell módosítania egy szabadható objektumot, annak megfagyasztása teljesítménybeli előnyöket biztosít. Ha ebben a példában lefagyasztaná az ecsetet, a grafikus rendszernek már nem kellene figyelnie az esetleges változásokat. A grafikus rendszer más optimalizálásokat is végezhet, mert tudja, hogy az ecset nem változik.

Megjegyzés:

Az egyszerűség kedvéért a fagyasztható objektumok fagymentesek maradnak, hacsak nem fagyasztja le őket kifejezetten.

Freezables használata

A nem fagyasztható objektumok használata olyan, mint bármely más típusú objektum használata. Az alábbi példában egy SolidColorBrush színe sárgáról pirosra változik, miután a gomb háttérszíneként használták fel. A grafikus rendszer a színfalak mögött dolgozik, hogy a képernyő következő frissítésekor automatikusan sárgáról pirosra módosítsa a gombot.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;

// Changes the button's background to red.
myBrush.Color = Colors.Red;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush


' Changes the button's background to red.
myBrush.Color = Colors.Red

Egy fagyasztható tárgy fagyasztása

A Freezable nem módosíthatóvá tétele érdekében meghívja annak Freeze metódusát. Egy, a fagyasztható objektumokat tartalmazó objektum lefagyasztásakor ezek az objektumok is lefagynak. Ha például lefagy egy PathGeometry, a benne szereplő adatok és szegmensek is le lesznek fagyasztva.

A fagyasztható nem lehet fagyasztani, ha az alábbiak bármelyike igaz:

  • Animált vagy adathoz kötött tulajdonságokkal rendelkezik.

  • Dinamikus erőforrás által beállított tulajdonságokkal rendelkezik. (A dinamikus erőforrásokról további információt a XAML-erőforrások talál.)

  • Olyan Freezable alobjektumokat tartalmaz, amelyek nem fagyaszthatók le.

Ha ezek a feltételek hamisak, és nem áll szándékában módosítani a Freezable-t, akkor le kell fagyasztania a korábban ismertetett teljesítménybeli előnyök eléréséhez.

Ha meghívja egy fagyasztható objektum Freeze metódusát, az már nem módosítható. A fagyasztott objektumok módosításának megkísérlése InvalidOperationException okoz. A következő kód kivételt jelez, mert a fagyasztás után megpróbáljuk módosítani az ecsetet.


Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

try {

    // Throws an InvalidOperationException, because the brush is frozen.
    myBrush.Color = Colors.Red;
}catch(InvalidOperationException ex)
{
    MessageBox.Show("Invalid operation: " + ex.ToString());
}


Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

myButton.Background = myBrush

Try

    ' Throws an InvalidOperationException, because the brush is frozen.
    myBrush.Color = Colors.Red
Catch ex As InvalidOperationException
    MessageBox.Show("Invalid operation: " & ex.ToString())
End Try

A kivétel elkerülése érdekében a IsFrozen metódussal megállapíthatja, hogy egy Freezable le van-e fagyasztva.


Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

if (myBrush.IsFrozen) // Evaluates to true.
{
    // If the brush is frozen, create a clone and
    // modify the clone.
    SolidColorBrush myBrushClone = myBrush.Clone();
    myBrushClone.Color = Colors.Red;
    myButton.Background = myBrushClone;
}
else
{
    // If the brush is not frozen,
    // it can be modified directly.
    myBrush.Color = Colors.Red;
}


Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

myButton.Background = myBrush


If myBrush.IsFrozen Then ' Evaluates to true.
    ' If the brush is frozen, create a clone and
    ' modify the clone.
    Dim myBrushClone As SolidColorBrush = myBrush.Clone()
    myBrushClone.Color = Colors.Red
    myButton.Background = myBrushClone
Else
    ' If the brush is not frozen,
    ' it can be modified directly.
    myBrush.Color = Colors.Red
End If


Az előző kód példában egy módosítható másolat készült egy fagyasztott objektumról a Clone metódus használatával. A következő szakasz részletesebben ismerteti a klónozást.

Megjegyzés:

Mivel a fagyasztott fagyasztható nem animálható, az animációs rendszer automatikusan módosítható klónokat hoz létre a fagyasztott Freezable objektumokból, amikor Storyboard-gyel próbálják őket animálni. A klónozás által okozott teljesítményterhelés megszüntetéséhez hagyja az objektumot befagyasztás nélkül, ha animálni szeretné. A storyboardokkal való animálásról további információt a Storyboards overviewcímű cikkben talál.

Lefagyás a Korrektúra alkalmazásból

A megjelölésben deklarált Freezable objektum lezárása a PresentationOptions:Freeze attribútummal történik. Az alábbi példában a SolidColorBrush laperőforrásként deklarálva lesz, és le van fagyasztva. Ezután egy gomb hátterének beállítására szolgál.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="PresentationOptions">

  <Page.Resources>

    <!-- This resource is frozen. -->
    <SolidColorBrush 
      x:Key="MyBrush"
      PresentationOptions:Freeze="True" 
      Color="Red" />
  </Page.Resources>


  <StackPanel>

    <Button Content="A Button" 
      Background="{StaticResource MyBrush}">
    </Button>

  </StackPanel>
</Page>

A Freeze attribútum használatához hozzá kell rendelnie a prezentációs lehetőségek névteréhez: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options. PresentationOptions a névtér leképezéséhez javasolt előtag:

xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"

Mivel nem minden XAML-olvasó ismeri fel ezt az attribútumot, javasoljuk, hogy az mc:Ignorable Attribútum használatával jelölje meg a PresentationOptions:Freeze attribútumot figyelmen kívül hagyhatóként:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"

További információ: mc:Ignorable Attribute oldalon.

"Feloldani egy fagyaszthatót"

A fagyasztás után a Freezable soha nem lehet módosítani vagy feloldani; a Clone vagy a CloneCurrentValue metódussal azonban létrehozhat egy feloldatlan klónt.

A következő példában a gomb hátterét egy kefével állítja be, és az ecset ezután le van fagyasztva. A Clone módszerrel a keféről készült fagymentes másolat készül. A klón módosul, és a gomb hátterének sárga színről pirosra való módosítására szolgál.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

// Freezing a Freezable before it provides
// performance improvements if you don't
// intend on modifying it.
if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

// If you need to modify a frozen brush,
// the Clone method can be used to
// create a modifiable copy.
SolidColorBrush myBrushClone = myBrush.Clone();

// Changing myBrushClone does not change
// the color of myButton, because its
// background is still set by myBrush.
myBrushClone.Color = Colors.Red;

// Replacing myBrush with myBrushClone
// makes the button change to red.
myButton.Background = myBrushClone;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

' Freezing a Freezable before it provides
' performance improvements if you don't
' intend on modifying it. 
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If


myButton.Background = myBrush

' If you need to modify a frozen brush,
' the Clone method can be used to
' create a modifiable copy.
Dim myBrushClone As SolidColorBrush = myBrush.Clone()

' Changing myBrushClone does not change
' the color of myButton, because its
' background is still set by myBrush.
myBrushClone.Color = Colors.Red

' Replacing myBrush with myBrushClone
' makes the button change to red.
myButton.Background = myBrushClone

Megjegyzés:

Függetlenül attól, hogy melyik klónmódszert használja, az animációk soha nem másolódnak át az új Freezable-ba.

A Clone és CloneCurrentValue metódusok a fagyasztható objektumok mély másolatait készítik. Ha a fagyasztható más fagyasztható objektumokat is tartalmaz, klónozzák és módosíthatóvá teszik őket. Ha például klónoz egy befagyasztott PathGeometry, hogy módosítható legyen, a benne lévő számok és szegmensek is másolódnak és módosíthatóvá lesznek.

Saját fagyasztható osztály létrehozása

A Freezable-ból leszármazó osztály a következő funkciókat nyeri el.

  • Különleges állapotok: írásvédett (fagyasztott) és írható állapot.

  • Szálbiztonság: egy fagyasztott Freezable megosztható a szálak között.

  • Részletes változásértesítés: Más DependencyObject-októl eltérően a Szabadon fagyasztható objektumok változásértesítést biztosítanak, amikor a tulajdonságok részértékei megváltoznak.

  • Egyszerű klónozás: a Fagyasztható osztály már számos olyan módszert implementált, amelyek mély klónokat hoznak létre.

A Freezable a DependencyObjecttípusa, ezért a függőségi tulajdonságrendszert használja. Az osztálytulajdonságoknak nem kell függőségi tulajdonságoknak lenniük, de a függőségi tulajdonságok használata csökkenti az írandó kód mennyiségét, mivel a Freezable osztályt a függőségi tulajdonságok szem előtt tartásával tervezték. A függőségi tulajdonságrendszerről további információt a Függőség tulajdonságainak áttekintésecímű témakörben talál.

Minden Freezable alosztálynak felül kell írnia a CreateInstanceCore metódust. Ha az osztály függőségi tulajdonságokat használ az összes adatához, befejeződött.

Ha az osztály nem függőségi tulajdonságadat-tagokat tartalmaz, felül kell bírálnia a következő metódusokat is:

A következő szabályokat is be kell tartania a nem függőségi tulajdonságokat tartalmazó adattagok elérésére és írására:

  • Minden olyan API elején, amely nem függőségi tulajdonságadat-tagokat olvas be, hívja meg a ReadPreamble metódust.

  • Minden olyan API elején, amely nem függőségi tulajdonságadat-tagokat ír, hívja meg a WritePreamble metódust. (Miután az WritePreamble-t meghívta egy API-ban, ha nem függőségi tulajdonságadat-tagokat is olvas, akkor nem szükséges további hívást kezdeményeznie a ReadPreamble-re.)

  • Hívja meg a WritePostscript metódust, mielőtt kilép a nem függőségi tulajdonságadat-tagoknak írt metódusok közül.

Ha az osztály olyan nem függőségi tulajdonságú adattagokat tartalmaz, amelyek DependencyObject objektumok, akkor is meg kell hívnia a OnFreezablePropertyChanged metódust minden alkalommal, amikor módosítja az egyik értéküket, még akkor is, ha a tagot nullértékre állítja.

Megjegyzés:

Nagyon fontos, hogy minden Freezable metódust, amelyet felülír, az alapimplementáció hívásával kezdjen.

Egy példa egyéni Freezable osztályra: lásd a Egyéni animációs minta.

Lásd még