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

V převážné většině případů jsou instance tříd Windows Runtime, jako jsou standardní objekty jazyka C++, přístupné z libovolného vlákna. Tyto třídy se označují jako "agilní". Malý počet tříd modulu runtime Windows, které jsou součástí Windows, ale nejsou agilní a musí se spotřebovávat více jako objekty MODELU COM než standardní objekty jazyka C++. K použití neagilních tříd nemusíte být odborníkem na model COM, ale musíte vzít v úvahu model vláken třídy a chování jejího zařazování. Tento článek obsahuje základní informace a pokyny pro tyto vzácné scénáře, ve kterých potřebujete využívat instanci neagilní třídy.

Model vláken a chování zařazování

Třída Windows Runtime může různými způsoby podporovat souběžný přístup k vláknu, jak je označeno dvěma atributy, které se na něj aplikují:

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

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

Atribut 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áří ThreadingModel objekt (oba). Hodnoty atributů odkazují na to, jak se objekt chová v různých kontextech vláken. Ve většině případů nemusíte tyto hodnoty podrobně MarshallingBehavior chápat. Z tříd poskytovaných rozhraním API Windows má přibližně 90 procent hodnotu =Obě a ThreadingModelMarshallingType =Agilní. To znamená, že mohou transparentně a efektivně zpracovávat podrobnosti o vláknech nízké úrovně. Když použijete k vytvoření "agilní" třídy, můžete na ní volat metody z hlavního vlákna aplikace nebo z jednoho nebo ref new více pracovních vláken. Jinými slovy, můžete použít agilní třídu – bez ohledu na to, jestli ji poskytuje Windows nebo třetí strana – z libovolného místa v kódu. Nemusíte mít obavy o model vláken třídy nebo chování zařazování.

Využívání komponent Windows Runtime

Při vytváření aplikace Univerzální Windows platformy můžete pracovat s agilní i neagilní komponentou. Při interakci s neagagilní komponentami může dojít k následujícímu upozornění.

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

Z různých důvodů některé třídy nejsou agilní. Pokud přistupujete k instancím neagilní tříd z vlákna uživatelského rozhraní i vlákna na pozadí, pak dbejte na to, abyste zajistili správné chování za běhu. Kompilátor Microsoft C++ vydává upozornění při vytváření instance neagilní třídy run-time v aplikaci v globálním oboru nebo při deklaraci neagilní typu jako člena třídy ve třídě ref, která je sama o sobě označená jako agilní.

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


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

Tady je upozornění, které se zobrazí:

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ího oboru) k objektu, který má zařazování chování "Standard", kompilátor vydá upozornění, které doporučuje zabalit typ v : Pokud použijete , můžete používat třídu stejně jako jakoukoli jinou Platform::Agile<T>Consider using 'Platform::Agile<Windows::Security::Credentials::UI::CredentialPickerOptions>' instead agilní Agile<T> 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 možnost, že použití kódu může poní it ukazatel – to znamená, že ho použijete v jiném objektu bez správného zařazování.

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

Následující příklad ukazuje, jak použít 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 Agile si, že nelze předat jako návratovou hodnotu nebo parametr ve třídě ref. Metoda vrátí popisovač (^), který můžete předat přes binární rozhraní aplikace (ABI) ve veřejné metodě Agile<T>::Get() nebo vlastnosti.

Při vytváření odkazu na třídu v prostředí Windows Runtime, která má zařazování chování "None", kompilátor vydá upozornění C4451, ale nenavrhuje použití Platform::Agile<T> . Kompilátor nemůže nabídnout žádnou pomoc nad rámec tohoto upozornění, takže je na vás, abyste správně používají třídu a zajistili, že váš kód volá komponenty STA pouze z vlákna uživatelského rozhraní a komponenty MTA pouze z vlákna na pozadí.

Vytváření agilní Windows Runtime

Když definujete třídu ref v jazyce C++/CX, je ve výchozím nastavení agilní – to znamená, že má =Both a ThreadingModelMarshallingType =Agilní. Pokud používáte knihovnu šablon C++ Windows Runtime, můžete třídu nastavit jako agilní odvozením z třídy , která FtmBase používá FreeThreadedMarshaller . Pokud vytváříte třídu, která ThreadingModel má =Both nebo =MTA, ujistěte se, že třída je bezpečná pro ThreadingModel více vláken.

Můžete upravit model vláken a chování zařazování třídy ref. Pokud ale změníte, které vykreslují třídu jako neagilní, musíte porozumět důsledkům, které jsou s těmito změnami spojené.

Následující příklad ukazuje, jak použít atributy a na třídu MarshalingBehaviorThreadingModel modulu runtime v knihovně tříd Windows Runtime. Pokud aplikace používá knihovnu DLL a k aktivaci objektu třídy používá klíčové slovo , aktivuje se objekt v objektu s jedním vláknem a nepodporuje ref newMySTAClass 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 vláken, aby kompilátor mohl ověřit, že odvozené třídy mají pro tyto atributy stejnou hodnotu. Pokud třída nemá explicitně nastavená nastavení, kompilátor vygeneruje chybu a nepodaří se ji zkompilovat. Jakákoli třída odvozená z nezapečetěné třídy vygeneruje chybu kompilátoru v jednom z těchto případů:

  • Atributy ThreadingModelMarshallingBehavior a nejsou definovány v odvozené třídě.

  • Hodnoty atributů a v odvozené třídě se neshodují s hodnotami ThreadingModelMarshallingBehavior v základní třídě.

Informace o vláknech a zařazování, které vyžaduje komponenta Windows Runtime třetí strany, jsou uvedené v registračních informacích manifestu aplikace pro komponentu. Doporučujeme, abyste všechny komponenty modulu runtime Windows agilní. Tím se zajistí, že kód klienta může volat vaši komponentu z jakéhokoli vlákna v aplikaci, a zlepší se výkon těchto volání, protože se jedná o přímá volání, která nemají žádné zařazování. Pokud svou třídu vytváříte tímto způsobem, pak klientský kód nemusí používat vaši Platform::Agile<T> třídu.

Viz také

ThreadingModel
Zařazování Behavior