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ýčtemThreadingModel
.MarshallingBehavior
atribut může mít jednu z hodnot – Agile, None nebo Standard, jak je definováno výčtemMarshallingType
.
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á ThreadingModel
př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
AtributyThreadingModel
nejsou definovány v odvozené třídě.Hodnoty
ThreadingModel
aMarshallingBehavior
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.