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


Szálkezelés és marsallálás (C++/CX)

Az esetek túlnyomó többségében a Windows futtatókörnyezeti osztályok példányai, például a standard C++ objektumok, bármely szálról elérhetők. Az ilyen osztályokat "agilisnak" nevezzük. A Windowst tartalmazó windowsos futtatókörnyezeti osztályok kis része azonban nem agilis, és inkább COM-objektumokat kell használni, mint a standard C++ objektumokat. Nem kell COM-szakértőnek lennie a nem agilis osztályok használatához, de figyelembe kell vennie az osztály szálkezelési modelljét és a használatbavételi viselkedését. Ez a cikk hátteret és útmutatást nyújt azokhoz a ritka esetekhez, amelyekben nem agilis osztály egy példányát kell használnia.

Szálmodell és a marsallálás viselkedése

A Windows futtatókörnyezeti osztály különböző módokon támogatja az egyidejű szálhozzáférést, ahogy azt két attribútum is jelzi:

  • ThreadingModel az attribútum az enumerálás által ThreadingModel definiált értékek egyikével rendelkezhet – STA, MTA vagy Mindkettő.

  • MarshallingBehavior az attribútum az enumerálás által MarshallingType definiált értékek egyikével rendelkezhet : Agile, None vagy Standard.

Az ThreadingModel attribútum megadja, hogy az osztály hol legyen betöltve aktiváláskor: csak felhasználói felületi szál (STA) környezetében, csak háttérszál (MTA) környezetében vagy az objektumot létrehozó szál környezetében (mindkettő). Az MarshallingBehavior attribútumértékek arra utalnak, hogy az objektum hogyan viselkedik a különböző szálösszefűzési környezetekben; a legtöbb esetben nem kell részletesen megértenie ezeket az értékeket. A Windows API által biztosított osztályok körülbelül 90%-a ThreadingModel=Mindkettő és MarshallingType=Agilis. Ez azt jelenti, hogy transzparensen és hatékonyan kezelhetik az alacsony szintű szálkezelés részleteit. Ha "agilis" osztályt hoz ref new létre, meghívhat metódusokat a fő alkalmazásszálból vagy egy vagy több feldolgozószálból. Más szóval a kód bármely pontjáról használhat agilis osztályt – függetlenül attól, hogy azt a Windows vagy egy harmadik fél biztosítja-e. Nem kell foglalkoznia az osztály szálmodelljével vagy a marshaling viselkedésével.

A Windows futtatókörnyezet összetevőinek használata

Univerzális Windows Platform-alkalmazás létrehozásakor az agilis és a nem agilis összetevőket is használhatja. Ha nem agilis összetevőkkel kommunikál, az alábbi figyelmeztetés jelenhet meg.

Fordító figyelmeztetés C4451 nem agilis osztályok használatakor

Különböző okokból egyes osztályok nem lehetnek mozgékonyak. Ha egy felhasználói felületi szálról és egy háttérszálról is hozzáfér a nem agilis osztályok példányaihoz, akkor fokozottan ügyeljen arra, hogy futásidőben megfelelő viselkedést biztosítson. A Microsoft C++ fordító figyelmeztetéseket ad ki, ha globális hatókörben példányosít egy nem agilis futásidejű osztályt az alkalmazásban, vagy nem agilis típust deklarál egy olyan ref osztály osztálytagjaként, amely maga agilisként van megjelölve.

A nem agilis osztályok közül a legegyszerűbben az =Both és MarshallingTypea =Standard osztályokkal ThreadingModelfoglalkozunk. Ezeket az osztályokat csak a Agile<T> segédosztály használatával teheti agilissá. Az alábbi példa egy nem agilis típusú objektum Windows::Security::Credentials::UI::CredentialPickerOptions^deklarációját és az eredményként kiadott fordítói figyelmeztetést mutatja be.

ref class MyOptions
    {
    public:
        property Windows::Security::Credentials::UI::CredentialPickerOptions^ Options

        {
            Windows::Security::Credentials::UI::CredentialPickerOptions^ get()
            {
                return _myOptions;
            }
        }
    private:
        Windows::Security::Credentials::UI::CredentialPickerOptions^ _myOptions;
    };

A következő figyelmeztetést adta ki:

Warning 1 warning C4451: 'Platform::Agile<T>::_object' : Usage of ref class 'Windows::Security::Credentials::UI::CredentialPickerOptions' inside this context can lead to invalid marshaling of object across contexts. Consider using 'Platform::Agile<Windows::Security::Credentials::UI::CredentialPickerOptions>' instead

Ha olyan objektumra ad hozzá egy hivatkozást – taghatókörben vagy globális hatókörben Platform::Agile<T>–, amelynek "Standard" a marshaling viselkedése, a fordító figyelmeztetést ad ki, amely arra figyelmezteti, hogy a típust a következőbe kell csomagolnia: Consider using 'Platform::Agile<Windows::Security::Credentials::UI::CredentialPickerOptions>' instead Ha használja Agile<T>, az osztályt úgy használhatja, mint bármely más agilis osztályt. Ilyen körülmények között használható Platform::Agile<T> :

  • A nem agilis változó globális hatókörben van deklarálva.

  • A nem agilis változó az osztály hatókörében deklarálva van, és előfordulhat, hogy a kód felhasználása csempészi a mutatót – azaz egy másik lakásban használja a megfelelő marsallálás nélkül.

Ha egyik feltétel sem érvényes, akkor a tartalmazó osztályt nem agilisként jelölheti meg. Más szóval közvetlenül csak nem agilis osztályokban kell tárolnia a nem agilis objektumokat, és nem agilis objektumokat kell tárolnia platformon keresztül::Agile<T> agilis osztályokban.

Az alábbi példa bemutatja, hogyan használható Agile<T> , hogy biztonságosan figyelmen kívül hagyhassa a figyelmeztetést.

#include <agile.h>
ref class MyOptions
    {
    public:
        property Windows::Security::Credentials::UI::CredentialPickerOptions^ Options

        {
            Windows::Security::Credentials::UI::CredentialPickerOptions^ get()
            {
                return m_myOptions.Get();
            }
        }
    private:
        Platform::Agile<Windows::Security::Credentials::UI::CredentialPickerOptions^> m_myOptions;

    };

Figyelje meg, hogy Agile nem adható át visszatérési értékként vagy paraméterként a ref osztályban. A Agile<T>::Get() metódus egy olyan leíró-objektumot (^) ad vissza, amelyet át lehet adni az alkalmazás bináris interfészén (ABI) egy nyilvános metódusban vagy tulajdonságban.

Amikor létrehoz egy olyan in-proc Windows futtatókörnyezeti osztályra mutató hivatkozást, amely a "None" nevű marshaling viselkedéssel rendelkezik, a fordító figyelmeztetést ad a C4451-nek, de nem javasolja, hogy fontolja meg a használatát Platform::Agile<T>. A fordító nem tud segítséget nyújtani a figyelmeztetésen túl, ezért az Ön feladata az osztály helyes használata, és annak biztosítása, hogy a kód csak a felhasználói felületi szálról hívja meg az STA-összetevőket, az MTA-összetevőket pedig csak háttérszálból.

Agilis Windows-futtatókörnyezeti összetevők létrehozása

Ha a C++/CX fájlban definiál egy ref osztályt, az alapértelmezés szerint agilis, ThreadingModelvagyis =Mindkettő és MarshallingType=Agile. Ha a Windows Runtime C++ sablontárat használja, az osztályt agilissá teheti a következőből FtmBaseszármaztatva:FreeThreadedMarshaller Ha olyan osztályt hoz létre, amely rendelkezik ThreadingModel=Both vagy ThreadingModel=MTA használatával, győződjön meg arról, hogy az osztály szálbiztos.

Módosíthatja a szálmodellt és a ref-osztályok marshaling viselkedését. Ha azonban olyan módosításokat hajt végre, amelyek nem agilissá teszik az osztályt, tisztában kell lennie a módosításokkal járó következményekkel.

Az alábbi példa bemutatja, hogyan alkalmazhatók MarshalingBehavior és ThreadingModel attribútumok egy futtatókörnyezeti osztályra egy Windows futtatókörnyezeti osztálytárban. Ha egy alkalmazás a DLL-t használja, és a ref new kulcsszót használja egy MySTAClass osztályobjektum aktiválásához, az objektum egyszálas lakásban aktiválódik, és nem támogatja a marsallást.

using namespace Windows::Foundation::Metadata;
using namespace Platform;

[Threading(ThreadingModel::STA)]
[MarshalingBehavior(MarshalingType::None)]
public ref class MySTAClass
{
};

A nem hozzárendelt osztályoknak rendelkezniük kell a marshaling és a threading attribútum beállításaival, hogy a fordító ellenőrizni tudja, hogy a származtatott osztályok azonos értékkel rendelkeznek-e ezekhez az attribútumokhoz. Ha az osztály nem rendelkezik explicit módon beállított beállításokkal, a fordító hibát okoz, és nem tud fordítást végrehajtani. A rendezetlen osztályból származtatott osztályok az alábbi esetekben fordítóhibát okoznak:

  • Az ThreadingModel és MarshallingBehavior az attribútumok nincsenek definiálva a származtatott osztályban.

  • A származtatott osztály értékei és MarshallingBehavior attribútumai nem egyeznek meg az alaposztályban szereplő értékekkelThreadingModel.

A harmadik féltől származó Windows Futtatókörnyezet-összetevő által megkövetelt szálkezelési és -készítési információk az összetevő alkalmazásjegyzék-regisztrációs adatai között találhatók. Javasoljuk, hogy az összes Windows Runtime-összetevőt mozgékonysá tegye. Ez biztosítja, hogy az ügyfélkód meghívja az összetevőt az alkalmazás bármely száláról, és javítja a hívások teljesítményét, mivel azok közvetlen hívások, amelyek nem rendelkeznek átirányítással. Ha így írja meg az osztályt, akkor az ügyfélkódot nem kell használnia Platform::Agile<T> az osztály használatához.

Lásd még

ThreadingModel
MarshallingBehavior