Erős és gyenge hivatkozások a C++/WinRT-ben

Fontos

A Windows App SDK-val fejleszt? A cikk kódja UWP-(Windows.UI.Xaml) névtereket használ. Ha a projekt a WinUI 3 -at (Windows App SDK) célozza meg, cserélje le Microsoft.UI.Xaml (és a kapcsolódó Microsoft.UI.* névterek) egészére. További részletekért tekintse meg az UWP API-k Windows App SDK való leképezését ismertető teljes leképezési és felhasználói felületi migrálási útmutatót.

A Windows-futtatókörnyezet referenciaszámlálásos rendszer, és egy ilyen rendszerben fontos tisztában lennie az erős és gyenge hivatkozások jelentőségével, valamint a közöttük lévő különbséggel (és az olyan hivatkozásokkal, amelyek egyike sem, például az implicit this mutatóval). Ahogy ebben a témakörben látni fogja, a hivatkozások helyes kezelésének ismerete jelentheti a gördülékenyen futó és a kiszámíthatatlan összeomlást okozó megbízható rendszer közötti különbséget. A nyelvi kivetítésben mély támogatást nyújtó segédfunkciók biztosításával a C++/WinRT félúton találkozik az összetettebb rendszerek egyszerű és helyes kiépítésével.

Note

Csak néhány kivételtől eltekintve a gyenge referenciák támogatása alapértelmezés szerint engedélyezve van a C++/WinRT-ben használt vagy létrehozott Windows-futtatókörnyezet-típusok esetében. Windows.UI.Composition és Windows.Devices.Input.PenDevice kivételek erre — vagyis olyan névterek, amelyekben a gyengereferencia-támogatás nincs engedélyezve ezekhez a típusokhoz. Lásd még: Ha az automatikus visszavonási meghatalmazott nem regisztrál.

Ha típusokat hoz létre, akkor tekintse meg a témakör Gyenge hivatkozások a C++/WinRT-ben című szakaszát.

A this mutató biztonságos elérése egy osztálytag-korutinban

A koroutinokról és a kódpéldákról további információt a C++/WinRT egyidejűségi és aszinkron műveleteiben talál.

Az alábbi kódlista egy tipikus példát mutat be egy olyan koroutinra, amely egy osztály tagfüggvénye. Ezt a példát egy új Windows konzolalkalmazás (C++/WinRT) projektben másolhatja be a megadott fájlokba.

// pch.h
#pragma once
#include <iostream>
#include <winrt/Windows.Foundation.h>

// main.cpp : Defines the entry point for the console application.
#include "pch.h"

using namespace winrt;
using namespace Windows::Foundation;
using namespace std::chrono_literals;

struct MyClass : winrt::implements<MyClass, IInspectable>
{
    winrt::hstring m_value{ L"Hello, World!" };

    IAsyncOperation<winrt::hstring> RetrieveValueAsync()
    {
        co_await 5s;
        co_return m_value;
    }
};

int main()
{
    winrt::init_apartment();

    auto myclass_instance{ winrt::make_self<MyClass>() };
    auto async{ myclass_instance->RetrieveValueAsync() };

    winrt::hstring result{ async.get() };
    std::wcout << result.c_str() << std::endl;
}

MyClass::RetrieveValueAsync egy ideig dolgozik, és végül visszaadja az MyClass::m_value adattag egy példányát. A RetrieveValueAsync meghívása egy aszinkron objektum létrehozását eredményezi, és ez az objektum rendelkezik egy implicit this mutatóval (amelyen keresztül végső soron a m_value érhető el).

Ne feledje, hogy a koroutinban a végrehajtás szinkronban van az első felfüggesztési pontig, ahol a vezérlés visszakerül a hívónak. A RetrieveValueAsyncben az első co_await az első felfüggesztési pont. Mire a korutin újra folytatódna (ebben az esetben körülbelül öt másodperccel később), bármi történhetett azzal az implicit this mutatóval, amelyen keresztül a m_value elemhez férünk hozzá.

Itt található az események teljes sorozata.

  1. Főként a MyClass egy példánya jön létre (myclass_instance).
  2. A async objektum jön létre, és a this elemén keresztül a(z) myclass_instance objektumra mutat.
  3. A winrt::Windows::Foundation::IAsyncAction::get függvény eléri az első felfüggesztési pontot, néhány másodpercig blokkol, majd visszaadja a RetrieveValueAsync eredményét.
  4. A RetrieveValueAsync a következő értéket this->m_valueadja vissza: .

A 4. lépés csak addig biztonságos, amíg ez érvényes marad.

De mi a teendő, ha az osztálypéldány az aszinkron művelet befejeződése előtt megsemmisül? Az osztálypéldány többféleképpen is kimehet a hatókörből, mielőtt az aszinkron metódus befejeződne. De ezt szimulálhatjuk azzal, hogy az osztálypéldányt nullptr értékre állítjuk.

int main()
{
    winrt::init_apartment();

    auto myclass_instance{ winrt::make_self<MyClass>() };
    auto async{ myclass_instance->RetrieveValueAsync() };
    myclass_instance = nullptr; // Simulate the class instance going out of scope.

    winrt::hstring result{ async.get() }; // Behavior is now undefined; crashing is likely.
    std::wcout << result.c_str() << std::endl;
}

Attól a ponttól kezdve, hogy töröljük az osztály egy példányát, úgy tűnik, hogy utána már nem hivatkozunk rá közvetlenül. Az aszinkron objektum azonban természetesen rendelkezik ezzel a mutatóval, és ezzel próbálja másolni az osztálypéldányban tárolt értéket. A korutin egy tagfüggvény, és abból indul ki, hogy aggályok nélkül használhatja a this mutatót.

A kód ezen módosításával a 4. lépésben problémába ütközünk, mert az osztálypéldány megsemmisült, és ez már nem érvényes. Amint az aszinkron objektum megpróbálja elérni a változót az osztálypéldányon belül, összeomlik (vagy teljesen meghatározatlan műveletet hajt végre).

A megoldás az, hogy az aszinkron műveletnek — a korutinnak — saját erős hivatkozást adunk az osztálypéldányra. Jelenlegi formájában a korutin gyakorlatilag egy nyers this mutatót tárol az osztálypéldányra; ez azonban nem elegendő ahhoz, hogy az osztálypéldány életben maradjon.

Az osztálypéldány életben tartásához módosítsa a RetrieveValueAsync implementációját az alább láthatóra.

IAsyncOperation<winrt::hstring> RetrieveValueAsync()
{
    auto strong_this{ get_strong() }; // Keep *this* alive.
    co_await 5s;
    co_return m_value;
}

A C++/WinRT-osztály közvetlenül vagy közvetve a winrt::implements sablonból származik . Emiatt a C++/WinRT objektum meghívhatja az implements::get_strong védett tagfüggvényét, hogy lekérjen egy erős hivatkozást a saját this mutatójára. Vegye figyelembe, hogy a fenti kódpéldában nincs szükség a strong_this változó tényleges használatára; a get_strong egyszerű meghívása növeli a C++/WinRT-objektum referenciaszámlálóját, és érvényben tartja az implicit this mutatót.

Fontos

Mivel a get_strong a winrt::implements struktúrasablon tagfüggvénye, csak olyan osztályból hívható meg, amely közvetlenül vagy közvetve a winrt::implements leszármazottja, például egy C++/WinRT-osztályból. A(z) winrt::implements osztályból való származtatásról további információkért, valamint példákért lásd: Author APIs with C++/WinRT.

Ez megoldja a korábban a 4. lépésben tapasztalt problémát. Még akkor is, ha az osztálypéldányra mutató összes többi hivatkozás eltűnik, a korutin megtette azt az óvintézkedést, hogy biztosítsa függőségeinek stabilitását.

Ha egy erős hivatkozás nem megfelelő, akkor ehelyett meghívhatja a(z) implements::get_weak függvényt, hogy lekérje a this gyenge hivatkozását. Csak győződjön meg arról, hogy tud szerezni egy erős hivatkozást, mielőtt hozzáfér a this elemhez. Ismét a get_weak a winrt::implements struktúrasablon tagfüggvénye.

IAsyncOperation<winrt::hstring> RetrieveValueAsync()
{
    auto weak_this{ get_weak() }; // Maybe keep *this* alive.

    co_await 5s;

    if (auto strong_this{ weak_this.get() })
    {
        co_return m_value;
    }
    else
    {
        co_return L"";
    }
}

A fenti példában a gyenge hivatkozás nem tartja meg az osztálypéldány megsemmisítését, ha nem maradnak erős hivatkozások. Ezzel azonban ellenőrizheti, hogy a tagváltozó elérése előtt beszerezhető-e erős hivatkozás.

Az egérmutató biztonságos elérése eseménykezelő meghatalmazottal

A forgatókönyv

Az eseménykezeléssel kapcsolatos általános információkért lásd: Események kezelése meghatalmazottak használatával a C++/WinRT-ben.

Az előző szakasz a korutinok és a konkurencia területén felmerülő lehetséges élettartam-problémákat emelte ki. Ha azonban egy eseményt egy objektum tagfüggvényével vagy egy lambda függvénnyel kezel egy objektum tagfüggvényén belül, akkor az esemény címzettjének (az eseményt kezelő objektumnak) és az esemény forrásának (az eseményt növelő objektumnak) relatív élettartamára kell gondolnia. Nézzünk meg néhány kódpéldát.

Az alábbi kódlista először egy egyszerű EventSource-osztályt határoz meg, amely egy általános eseményt hoz létre, amelyet a hozzá hozzáadott meghatalmazottak kezelnek. Ez a példaesemény a következő Windows::Foundation::EventHandler delegálási típust használja, de az itt ismertetett problémák és jogorvoslatok minden delegált típusra érvényesek.

Ezután az EventRecipient osztály egy kezelőt biztosít az EventSource::Event eseményhez lambda függvény formájában.

// pch.h
#pragma once
#include <iostream>
#include <winrt/Windows.Foundation.h>

// main.cpp : Defines the entry point for the console application.
#include "pch.h"

using namespace winrt;
using namespace Windows::Foundation;

struct EventSource
{
    winrt::event<EventHandler<int>> m_event;

    void Event(EventHandler<int> const& handler)
    {
        m_event.add(handler);
    }

    void RaiseEvent()
    {
        m_event(nullptr, 0);
    }
};

struct EventRecipient : winrt::implements<EventRecipient, IInspectable>
{
    winrt::hstring m_value{ L"Hello, World!" };

    void Register(EventSource& event_source)
    {
        event_source.Event([&](auto&& ...)
        {
            std::wcout << m_value.c_str() << std::endl;
        });
    }
};

int main()
{
    winrt::init_apartment();

    EventSource event_source;
    auto event_recipient{ winrt::make_self<EventRecipient>() };
    event_recipient->Register(event_source);
    event_source.RaiseEvent();
}

A minta lényege az, hogy az esemény fogadója egy lambda eseménykezelővel rendelkezik, amely a this mutatótól függ. Amikor az esemény címzettje túllépi az eseményforrást, az túllépi ezeket a függőségeket. És ezekben az esetekben, amelyek gyakoriak, a minta jól működik. Néhány ilyen eset nyilvánvaló, például amikor egy felhasználói felületi oldal kezeli az oldalon található vezérlőelem által kiváltott eseményt. Az oldal tovább él, mint a gomb – így az eseménykezelő is tovább él, mint a gomb. Ez minden alkalommal igaz, amikor a címzett a forrás tulajdonosa (például adattagként), vagy amikor a címzett és a forrás testvérei, és közvetlenül egy másik objektum tulajdonában van.

Ha biztos benne, hogy olyan esetről van szó, amikor a kezelő nem éli túl azt a this példányt, amelytől függ, akkor a this elemet a szokásos módon elkaphatja, anélkül, hogy figyelembe venné az erős vagy gyenge élettartamot.

Vannak azonban még olyan esetek, amikor a this élettartama nem tart ki addig, amíg egy eseménykezelő használja (beleértve az aszinkron tevékenységek és műveletek által kiváltott befejezési és folyamatjelző események kezelőit is), és fontos tudni, hogyan kell kezelni ezeket a helyzeteket.

  • Ha egy eseményforrás szinkron módon emeli az eseményeket, visszavonhatja a kezelőt, és biztos lehet abban, hogy nem fog több eseményt kapni. Az aszinkron események esetében azonban még a visszavonás után is (és különösen a destruktoron belüli visszavonáskor) egy repülés közbeni esemény a destruktúra megkezdése után is elérheti az objektumot. Ha még a megsemmisítés előtt talál egy leiratkozási lehetőséget, az enyhítheti a problémát, de egy megbízható megoldásért olvasson tovább.
  • Ha egy aszinkron metódus megvalósításához korutint ír, akkor ez lehetséges.
  • Bizonyos XAML felhasználói felületi keretrendszer-objektumokkal (például SwapChainPanel) ritkán előfordulhat, hogy a címzett véglegesítése az eseményforrás regisztrációjának törlése nélkül történik.

A probléma

A függvény következő verziója szimulálja, hogy mi történik, ha az esemény címzettje elpusztul (talán kimegy a hatókörből), miközben az eseményforrás még mindig eseményeket emel ki.

int main()
{
    winrt::init_apartment();

    EventSource event_source;
    auto event_recipient{ winrt::make_self<EventRecipient>() };
    event_recipient->Register(event_source);
    event_recipient = nullptr; // Simulate the event recipient going out of scope.
    event_source.RaiseEvent(); // Behavior is now undefined within the lambda event handler; crashing is likely.
}

Az esemény címzettje megsemmisül, de a benne lévő lambda eseménykezelő továbbra is előfizetett az eseményre . Az esemény felmerülésekor a lambda megkísérli elhalasztani ezt a mutatót, amely az adott időpontban érvénytelen. Tehát hozzáférési hiba akkor következik be, amikor a kezelőben lévő kód (vagy egy coroutine folytatásában lévő kód) megpróbálja használni azt.

Fontos

Ha ilyen helyzetbe ütközik, akkor gondolnia kell az objektum élettartamára; és hogy a rögzített objektum túllépi-e a rögzítést. Ha nem, akkor hivatkozzon rá erős vagy gyenge referenciával, ahogy azt alább bemutatjuk.

Vagy – ha ez az adott helyzetben értelmes, és ha a szálkezelési megfontolások ezt egyáltalán lehetővé teszik – egy másik lehetőség az eseménykezelő leválasztása, miután a címzett végzett az esemény feldolgozásával, vagy a címzett destruktorában. Lásd: A regisztrált delegált visszavonása.

Így regisztráljuk a kezelőt.

event_source.Event([&](auto&& ...)
{
    std::wcout << m_value.c_str() << std::endl;
});

A lambda automatikusan rögzíti a helyi változókat hivatkozás alapján. Tehát ebben a példában ezt is megírhattuk volna.

event_source.Event([this](auto&& ...)
{
    std::wcout << m_value.c_str() << std::endl;
});

Mindkét esetben csak a nyers mutatót rögzítjük. És ez nincs hatással a hivatkozásszámlálásra, így semmi sem akadályozza meg a jelenlegi objektum elpusztítását.

A megoldás

A megoldás egy erős hivatkozás rögzítése (vagy, amint látni fogjuk, gyenge hivatkozás, ha ez megfelelőbb). Az erős hivatkozás növeli a referenciaszámot, és életben tartja az aktuális objektumot. Egyszerűen deklarál egy befogóváltozót (amelyet ebben a példában strong_this-nak nevezünk), és inicializálja azt a implements::get_strong meghívásával, amely lekéri a this mutatónkra mutató erős referenciát.

Fontos

Mivel a get_strong a winrt::implements struktúrasablon tagfüggvénye, csak olyan osztályból hívható meg, amely közvetlenül vagy közvetve a winrt::implements leszármazottja, például egy C++/WinRT-osztályból. További információkért a(z) winrt::implements osztályból való származtatásról, valamint példákért lásd a következőt: Author APIs with C++/WinRT.

event_source.Event([this, strong_this { get_strong()}](auto&& ...)
{
    std::wcout << m_value.c_str() << std::endl;
});

Akár az aktuális objektum automatikus befogását is elhagyhatja, és az adattagot a befogási változó segítségével érheti el az implicit this helyett.

event_source.Event([strong_this { get_strong()}](auto&& ...)
{
    std::wcout << strong_this->m_value.c_str() << std::endl;
});

Ha egy erős hivatkozás nem megfelelő, akkor ehelyett meghívhatja a(z) implements::get_weak függvényt, hogy lekérje a this gyenge hivatkozását. A gyenge hivatkozás nem tartja életben az aktuális objektumot. Tehát csak győződjön meg arról, hogy továbbra is lekérhet egy erős hivatkozást a gyenge hivatkozásból, mielőtt hozzáfér a tagokhoz.

event_source.Event([weak_this{ get_weak() }](auto&& ...)
{
    if (auto strong_this{ weak_this.get() })
    {
        std::wcout << strong_this->m_value.c_str() << std::endl;
    }
});

Ha egy nyers mutatót fog el, akkor gondoskodnia kell arról, hogy a mutató által hivatkozott objektum életben maradjon.

Ha tagfüggvényt használ meghatalmazottként

A lambda függvények mellett ezek az alapelvek a tagfüggvények meghatalmazottként való használatára is érvényesek. A szintaxis eltérő, ezért tekintsünk meg néhány kódot. Először is itt található a potenciálisan nem biztonságos tagfüggvény eseménykezelője, amely nyersen használja ezt a mutatót.

struct EventRecipient : winrt::implements<EventRecipient, IInspectable>
{
    winrt::hstring m_value{ L"Hello, World!" };

    void Register(EventSource& event_source)
    {
        event_source.Event({ this, &EventRecipient::OnEvent });
    }

    void OnEvent(IInspectable const& /* sender */, int /* args */)
    {
        std::wcout << m_value.c_str() << std::endl;
    }
};

Ez az objektumra és tagfüggvényére való hivatkozás szabványos, hagyományos módja. A biztonság érdekében a Windows SDK 10.0.17763.0-s verziójától (Windows 10, 1809-es verzió) erős vagy gyenge referenciát hozhat létre a kezelő regisztrálásakor. Ezen a ponton már tudható, hogy az eseményt fogadó objektum még létezik.

Erős referencia esetén egyszerűen hívja meg a get_strong függvényt a nyers this mutató helyett. A C++/WinRT biztosítja, hogy az eredményként kapott meghatalmazott erős hivatkozást tartalmazzon az aktuális objektumra.

event_source.Event({ get_strong(), &EventRecipient::OnEvent });

Az erős hivatkozás rögzítése azt jelenti, hogy az objektum csak a kezelő regisztrációjának törlése és az összes hátralévő visszahívás visszahívása után lesz jogosult a megsemmisítésre. Ez a garancia azonban csak az esemény felmerülésének időpontjában érvényes. Ha az eseménykezelő aszinkron, akkor az első felfüggesztési pont előtt erős hivatkozást kell biztosítania a korutin számára az osztálypéldányra (a részletekért és a kódért lásd a témakör korábbi Az osztálytag korutinban a this mutató biztonságos elérése című szakaszát). Ez azonban körkörös hivatkozást hoz létre az eseményforrás és az objektum között, ezért explicit módon meg kell szakítania ezt az esemény visszavonásával.

Gyenge referenciához hívja meg a(z) get_weak függvényt. A C++/WinRT biztosítja, hogy az eredményül kapott meghatalmazott gyenge referenciával rendelkezik. Az utolsó pillanatban, a színfalak mögött a delegált megpróbálja a gyenge referenciát erős referenciává alakítani, és csak akkor hívja meg a tagfüggvényt, ha ez sikerül.

event_source.Event({ get_weak(), &EventRecipient::OnEvent });

Ha a meghatalmazott meghívja a tagfüggvényt, a C++/WinRT addig életben tartja az objektumot, amíg a kezelő vissza nem tér. Ha azonban a kezelő aszinkron, akkor a felfüggesztési pontokon tér vissza, ezért a koroutinnak erős hivatkozást kell adnia az osztálypéldányra az első felfüggesztési pont előtt. Ismét: további információért lásd az ebben a témakörben korábban szereplő A this mutató biztonságos elérése osztálytag korutinban című szakaszt.

Ha a tagfüggvény nem tartozik Windows-futtatókörnyezet típushoz

Ha a get_strong metódus nem érhető el (a típus nem Windows-futtatókörnyezet típus), használhatja az alábbi kód példájában látható technikát. Itt egy normál C++ osztály (neve ConsoleNetworkWatcher) jelenik meg, amely a NetworkInformation.NetworkStatusChanged eseményt kezeli.

#include <winrt/Windows.Networking.Connectivity.h>
using namespace winrt;
using namespace Windows::Networking::Connectivity;

class ConsoleNetworkWatcher
{
    /* any constructor, and instance methods, here*/

    static void Initialize(std::shared_ptr<ConsoleNetworkWatcher> instance)
    {
        auto weakPointer{ std::weak_ptr{ instance } };

        instance->m_statusChangedRevoker =
            NetworkInformation::NetworkStatusChanged(winrt::auto_revoke,
                [weakPointer](winrt::Windows::Foundation::IInspectable const& sender)
                {
                    auto sharedPointer{ weakPointer.lock() };

                    if (sharedPointer)
                    {
                        sharedPointer->NetworkStatusChanged(sender);
                    }
                });
    }

    void NetworkStatusChanged(winrt::Windows::Foundation::IInspectable const& sender){/* handle event here */};

private:
    NetworkInformation::NetworkStatusChanged_revoker m_statusChangedRevoker;
};

Példa gyenge referenciára a(z) SwapChainPanel::CompositionScaleChanged használatával

Ebben a kód példában a SwapChainPanel::CompositionScaleChanged eseményt használjuk a gyenge hivatkozások egy másik illusztrációja alapján. A kód egy eseménykezelőt regisztrál egy lambda használatával, amely gyenge hivatkozást rögzít a címzettre.

winrt::Microsoft::UI::Xaml::Controls::SwapChainPanel m_swapChainPanel;
winrt::event_token m_compositionScaleChangedEventToken;

void RegisterEventHandler()
{
    m_compositionScaleChangedEventToken = m_swapChainPanel.CompositionScaleChanged([weak_this{ get_weak() }]
        (Microsoft::UI::Xaml::Controls::SwapChainPanel const& sender,
        Windows::Foundation::IInspectable const& object)
    {
        if (auto strong_this{ weak_this.get() })
        {
            strong_this->OnCompositionScaleChanged(sender, object);
        }
    });
}

void OnCompositionScaleChanged(Microsoft::UI::Xaml::Controls::SwapChainPanel const& sender,
    Windows::Foundation::IInspectable const& object)
{
    // Here, we know that the "this" object is valid.
}

A lamba rögzítési záradékában egy ideiglenes változó jön létre, amely gyenge hivatkozást jelent erre. A lambda törzsében, ha erős referencia szerezhető a(z) this objektumra, akkor meghívódik a(z) OnCompositionScaleChanged függvény. Így az OnCompositionScaleChangeden belül ez biztonságosan használható.

Gyenge hivatkozások a C++/WinRT-ben

A fentiekben gyenge hivatkozásokat használtunk. Általában jól használhatók a ciklikus hivatkozások megszüntetésére. Például az XAML-alapú felhasználói felületi keretrendszer natív implementációjához – a keretrendszer korábbi kialakítása miatt – a C++/WinRT gyenge referenciamechanizmusa szükséges a ciklikus hivatkozások kezeléséhez. Az XAML-en kívül azonban valószínűleg nem kell gyenge hivatkozásokat használnia (nem mintha bármi XAML-specifikus lenne velük kapcsolatban). Inkább érdemes lehet saját C++/WinRT API-kat úgy megtervezni, hogy ne legyen szükség ciklikus hivatkozásokra és gyenge hivatkozásokra.

A deklarált típusok esetében nem egyértelmű azonnal a C++/WinRT számára, hogy szükség van-e gyenge hivatkozásokra. A C++/WinRT tehát automatikusan gyenge referenciatámogatást biztosít a winrt::implements szerkezetsablonon, amelyből a saját C++/WinRT-típusok közvetlenül vagy közvetve származnak. Ez egy fizetős játék, mivel nem kerül semmibe, hacsak az objektumot nem kérdezi le az IWeakReferenceSource. És explicit módon dönthet úgy, hogy kikapcsolja ezt a támogatást.

Példakódok

A winrt::weak_ref struct sablon az egyik lehetőség az osztálypéldány gyenge hivatkozásának lekérésére.

Class c;
winrt::weak_ref<Class> weak{ c };

Vagy használhatja a winrt::make_weak segédfüggvényt.

Class c;
auto weak = winrt::make_weak(c);

Gyenge hivatkozás létrehozása nem befolyásolja az objektum referenciaszámát; ez csak egy vezérlőblokk lefoglalását okozza. Ez a vezérlőblokk gondoskodik a gyenge referenciaszemantika implementálásáról. Ezután megpróbálhatja előléptetni a gyenge hivatkozást egy erős hivatkozásra, és ha sikeres, használja.

if (Class strong = weak.get())
{
    // use strong, for example strong.DoWork();
}

Feltéve, hogy még létezik egy másik erős hivatkozás, a weak_ref::get hívás növeli a referenciaszámlálót, és visszaadja az erős hivatkozást a hívónak.

A gyenge referenciatámogatás elutasítása

A gyenge referenciák támogatása automatikus. A winrt::no_weak_ref jelölőstruktúra sablonargumentumként való átadásával azonban explicit módon lemondhatja ezt a támogatást az alaposztálynak.

Ha közvetlenül a winrt::implements függvényből származik.

struct MyImplementation: implements<MyImplementation, IStringable, no_weak_ref>
{
    ...
}

Ha futtatókörnyezeti osztályt hoz létre.

struct MyRuntimeClass: MyRuntimeClassT<MyRuntimeClass, no_weak_ref>
{
    ...
}

Nem számít, hogy a variadikus paramétercsomagban hol jelenik meg a jelölőstruktúra. Ha gyenge referenciát kér egy olyan típushoz, amelynél ez a támogatás ki van kapcsolva, akkor a fordító ezzel az üzenettel segít: "Ez csak a gyengehivatkozás-támogatáshoz használható".

Fontos API-k