Agilis objektumok a C++/WinRT-ben

Az esetek túlnyomó többségében egy Windows-futtatókörnyezet osztály egy példánya bármely szálról elérhető (ahogyan a legtöbb standard C++ objektum is). Egy ilyen Windows-futtatókörnyezet osztály agilis. Csak kevés, a Windows által biztosított Windows-futtatókörnyezet-osztály nem agilis, de használatukkor figyelembe kell vennie a szálkezelési modelljüket és a marshaling működését (a marshaling az adatok átadását jelenti egy apartmanhatáron keresztül). Minden Windows-futtatókörnyezet objektum esetében ez az alapértelmezett beállítás, így a saját C++/WinRT-típusok alapértelmezés szerint agilisak.

De dönthet úgy is, hogy kimarad belőle. Előfordulhat például, hogy nyomós oka van megkövetelni, hogy az Ön típusának egy objektuma egy adott egyszálú apartmentben legyen. Ez általában a reentrancia-követelményekkel kapcsolatos. De egyre inkább a felhasználói felületi (UI) API-k is agilis objektumokat kínálnak. Általában az agilitás a legegyszerűbb és legmegvalósítóbb lehetőség. Emellett, amikor megvalósít egy aktiválási gyárat, annak akkor is agilisnak kell lennie, ha a kapcsolódó futásidejű osztály nem az.

Note

A Windows-futtatókörnyezet a COM-n alapul. COM-ban egy agilis osztály van regisztrálva ThreadingModel = . A COM menetmodellekről és az apartmanokról további információt a COM menetmodellek ismertetése és használata című témakörben talál.

Példakódok

Használjunk példaként egy futtatókörnyezeti osztályt annak bemutatására, hogy a C++/WinRT hogyan támogatja az agilitást.

#include <winrt/Windows.Foundation.h>

using namespace winrt;
using namespace Windows::Foundation;

struct MyType : winrt::implements<MyType, IStringable>
{
    winrt::hstring ToString(){ ... }
};

Mivel nem léptünk ki, ez a megvalósítás rugalmas. A winrt::implementálja azIAgileObject és az IMarshal alapstruktúra implementálását. Az IMarshal-implementáció a CoCreateFreeThreadedMarshaler használatával helyesen hajtja végre az IAgileObjectről nem ismert régi kódokat.

Ez a kód ellenőrzi az objektum rugalmasságát. Az IUnknown::as hívás kivételt eredményez, ha myimpl nem agilis.

winrt::com_ptr<MyType> myimpl{ winrt::make_self<MyType>() };
winrt::com_ptr<IAgileObject> iagileobject{ myimpl.as<IAgileObject>() };

A kivétel kezelése helyett inkább a(z) IUnknown::try_as elemet hívhatja meg.

winrt::com_ptr<IAgileObject> iagileobject{ myimpl.try_as<IAgileObject>() };
if (iagileobject) { /* myimpl is agile. */ }

Az IAgileObject nem rendelkezik saját metódusokkal, így nem sokat tehet vele. Ez a következő változat sokkal jellemzőbb.

if (myimpl.try_as<IAgileObject>()) { /* myimpl is agile. */ }

Az IAgileObject egy jelölőfelület. Az IAgileObject lekérdezésének puszta sikeressége vagy sikertelensége a tőle kapott információk és segédprogramok mértéke.

Az agilis objektumok támogatásának letiltása

A winrt::non_agile jelölőstruktúra sablonargumentumként való átadásával explicit módon kikapcsolhatja az agilis objektumok támogatását az alaposztálynak.

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

struct MyImplementation: implements<MyImplementation, IStringable, winrt::non_agile>
{
    ...
}

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

struct MyRuntimeClass: MyRuntimeClassT<MyRuntimeClass, winrt::non_agile>
{
    ...
}

Nem számít, hogy a variadikus paramétercsomagban hol jelenik meg a jelölőstruktúra.

Akár lemond az agilitásról, akár nem, az IMarshal felületet saját maga is implementálhatja. Használhatja például a winrt::non_agile jelölőt az alapértelmezett rugalmassági implementáció elkerüléséhez, és saját maga implementálhatja az IMarshalt – talán az értékenkénti szemantikák támogatásához.

Agilis hivatkozások (winrt::agile_ref)

Ha olyan objektumot használ, amely nem agilis, de valamilyen potenciálisan agilis környezetben kell átadnia, akkor az egyik lehetőség a winrt::agile_ref struct sablon használata egy nem agilis típusú példányra vagy egy nem agilis objektum felületére mutató agilis hivatkozás lekéréséhez.

NonAgileType nonagile_obj;
winrt::agile_ref<NonAgileType> agile{ nonagile_obj };

Használhatja a winrt::make_agile segédfüggvényt is.

NonAgileType nonagile_obj;
auto agile{ winrt::make_agile(nonagile_obj) };

Mindkét esetben a agile most már szabadon átadható egy másik apartmanban futó szálnak, és ott használható.

co_await resume_background();
NonAgileType nonagile_obj_again{ agile.get() };
winrt::hstring message{ nonagile_obj_again.Message() };

A agile_ref::get hívás egy proxyt ad vissza, amely biztonságosan használható abban a szálkörnyezetben, amelyben a lekérés meghívásra kerül.

Fontos API-k