Dělení do vláken a zařazování (C++/CX)

Ve většině případů lze instance prostředí Windows Runtime tříd, jako jsou standardní objekty C++, přístupné z libovolného vlákna. Takové třídy se označují jako "agilní". Malý počet tříd prostředí Windows Runtime, které jsou dodávány se systémem Windows, jsou neagilní a musí být využity více jako objekty MODELU COM než standardní objekty C++. Abyste mohli používat agilní třídy, nemusíte být odborníkem modelu COM, ale musíte vzít v úvahu model vláken třídy a jeho chování zařazování. Tento článek obsahuje základní informace a pokyny pro ty vzácné scénáře, ve kterých potřebujete využívat instanci agilní třídy.

Chování při zařazování modelů vláken a zařazování

Třída prostředí Windows Runtime může podporovat souběžný přístup k vláknům různými způsoby, jak je uvedeno dvěma atributy, které jsou na něj použity:

  • ThreadingModel atribut může mít jednu z hodnot – STA, MTA nebo Both, jak je definováno výčtem ThreadingModel .

  • MarshallingBehavior atribut může mít jednu z hodnot – Agile, None nebo Standard, jak je definováno výčtem MarshallingType .

Atribut ThreadingModel určuje, kde je třída načtena při aktivaci: pouze v kontextu vlákna uživatelského rozhraní (STA), pouze v kontextu vlákna na pozadí (MTA) nebo v kontextu vlákna, které vytváří objekt (Oba). Hodnoty MarshallingBehavior atributů odkazují na to, jak se objekt chová v různých kontextech vláken. Ve většině případů tyto hodnoty nemusíte podrobně pochopit. Z tříd poskytovaných rozhraním API systému Windows má ThreadingModelpřibližně 90 procent =Obě a MarshallingType=Agilní. To znamená, že můžou zpracovávat podrobnosti s nízkými úrovněmi vláken transparentně a efektivně. Když použijete ref new k vytvoření "agilní" třídy, můžete na ni volat metody z hlavního vlákna aplikace nebo z jednoho nebo více pracovních vláken. Jinými slovy, můžete použít agilní třídu – bez ohledu na to, jestli je poskytována systémem Windows nebo třetí stranou – odkudkoliv ve vašem kódu. Nemusíte se zabývat modelem vláken třídy ani chováním zařazování.

Využívání komponent prostředí Windows Runtime

Při vytváření Univerzální platforma Windows aplikace můžete pracovat s agilními i negilními komponentami. Při interakci s neaktivními komponentami se může zobrazit následující upozornění.

Upozornění kompilátoru C4451 při využívání agilních tříd

Z různých důvodů některé třídy nemůžou být agilní. Pokud přistupujete k instancím agilních tříd z vlákna uživatelského rozhraní i vlákna na pozadí, ujistěte se, že je v době běhu správné chování. Kompilátor Microsoft C++ vydává upozornění, když v aplikaci vytvoříte instanci negilní třídy runtime v globálním rozsahu nebo deklarujete negilní typ jako člen třídy ref, který je sám označený jako agilní.

Z neagilních tříd je nejjednodušší řešit ty, které mají ThreadingModel=Obě a MarshallingType=Standard. Tyto třídy můžete agilní jenom pomocí Agile<T> pomocné třídy. Následující příklad ukazuje deklaraci neagilního objektu typu Windows::Security::Credentials::UI::CredentialPickerOptions^a upozornění kompilátoru, které je vydáno jako výsledek.

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;
    };

Toto je upozornění, které je vydáno:

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

Když přidáte odkaz ( v oboru člena nebo globálním oboru) k objektu, který má zařazování chování "Standard", kompilátor vydá upozornění, které doporučuje zabalit typ Platform::Agile<T>do : Consider using 'Platform::Agile<Windows::Security::Credentials::UI::CredentialPickerOptions>' instead Pokud používáte Agile<T>, můžete třídu využívat stejně jako jakoukoli jinou agilní třídu. Použití Platform::Agile<T> za těchto okolností:

  • Neagilní proměnná je deklarována v globálním oboru.

  • Neagilní proměnná je deklarována v oboru třídy a existuje šance, že by používání kódu mohlo pašovat ukazatel – to znamená použít v jiném bytě bez správného zařazování.

Pokud se žádná z těchto podmínek nepoužije, můžete třídu obsahující označit jako agilní. Jinými slovy, měli byste přímo uchovávat neagilní objekty pouze v agilních třídách a uchovávat neagilní objekty prostřednictvím platformy::Agile<T> v agilních třídách.

Následující příklad ukazuje, jak používat Agile<T> , abyste mohli upozornění bezpečně ignorovat.

#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;

    };

Všimněte si, že Agile nelze předat jako návratovou hodnotu nebo parametr ve třídě ref. Metoda Agile<T>::Get() vrátí metodu handle-to-object (^), kterou můžete předat v binárním rozhraní aplikace (ABI) ve veřejné metodě nebo vlastnosti.

Při vytváření odkazu na in-proc prostředí Windows Runtime třídy, která má zařazování chování None, kompilátor problémy s upozorněním C4451, ale nenavrhuje, že byste měli zvážit použití Platform::Agile<T>. Kompilátor nemůže nabídnout žádnou pomoc nad rámec tohoto upozornění, takže je vaší zodpovědností používat třídu správně a zajistit, aby kód volal komponenty STA pouze z vlákna uživatelského rozhraní a komponenty MTA pouze z vlákna na pozadí.

Vytváření agilních komponent prostředí Windows Runtime

Když definujete ref třídu v jazyce C++/CX, je ve výchozím nastavení agilní – to znamená, že má ThreadingModel=Obě a MarshallingType=Agile. Pokud používáte knihovnu šablon jazyka C++ prostředí Windows Runtime, můžete svoji třídu agilní odvozením z FtmBase, která používá FreeThreadedMarshaller. Pokud vytvoříte třídu, která má ThreadingModel=Obě nebo ThreadingModel=MTA, ujistěte se, že je třída bezpečná pro přístup z více vláken.

Model threadingu a zařazování chování třídy ref můžete upravit. Pokud ale provedete změny, které vykreslí třídu agilní, musíte pochopit důsledky, které jsou k těmto změnám přidružené.

Následující příklad ukazuje, jak použít MarshalingBehavior a ThreadingModel atributy třídy runtime v knihovně tříd prostředí Windows Runtime. Když aplikace používá knihovnu DLL a k aktivaci objektu MySTAClass třídy používá ref new klíčové slovo, objekt se aktivuje v apartmánu s jedním vláknem a nepodporuje zařazování.

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

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

Nezapečetěná třída musí mít nastavení atributu zařazování a zařazování vláken, aby kompilátor mohl ověřit, že odvozené třídy mají pro tyto atributy stejnou hodnotu. Pokud třída nemá nastavená nastavení explicitně, kompilátor vygeneruje chybu a nepodaří se zkompilovat. Každá třída odvozená z nezapečetěné třídy generuje chybu kompilátoru v některém z těchto případů:

  • MarshallingBehavior Atributy ThreadingModel nejsou definovány v odvozené třídě.

  • Hodnoty ThreadingModel a MarshallingBehavior atributy v odvozené třídě neodpovídají hodnotám v základní třídě.

Informace o zařazování a zařazování vláken vyžadované komponentou prostředí Windows Runtime třetí strany jsou určené v registračních informacích manifestu aplikace pro danou komponentu. Doporučujeme, abyste všechny komponenty prostředí Windows Runtime agilní. Tím zajistíte, že klientský kód bude moct volat komponentu z libovolného vlákna v aplikaci a zlepšit výkon těchto volání, protože se jedná o přímá volání, která nemají žádné zařazování. Pokud předmět vytvoříte tímto způsobem, klientský kód se nemusí používat Platform::Agile<T> k využívání předmětu.

Viz také

ThreadingModel
MarshallingBehavior