Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Na grande maioria dos casos, uma instância de uma classe Windows Runtime pode ser acessada de qualquer thread (assim como a maioria dos objetos C++ padrão pode). Essa classe Windows Runtime é ágil. Apenas um pequeno número de classes do Windows Runtime fornecidas com o Windows não são ágeis, mas, ao utilizá-las, você precisa levar em consideração o modelo de thread e o comportamento de marshaling delas (marshaling é a passagem de dados entre limites de apartment). É uma boa configuração padrão que todo objeto do Windows Runtime seja ágil, portanto seus próprios tipos C++/WinRT também são ágeis por padrão.
Mas você pode optar por não participar. Você pode ter um motivo convincente para exigir que um objeto desse tipo fique, por exemplo, em um determinado apartamento de thread única. Normalmente, isso tem a ver com os requisitos de reentração. Mas cada vez mais, até mesmo as APIs de interface do usuário (UI) oferecem objetos ágeis. Em geral, a agilidade é a opção mais simples e com maior desempenho. Além disso, quando você implementa uma fábrica de ativação, ela deve ser ágil mesmo se a classe de runtime correspondente não estiver.
Note
O Windows Runtime é baseado em COM. Em termos COM, uma classe agile é registrada com ThreadingModel = Both. Para obter mais informações sobre os modelos de threading do COM e apartments, consulte Entendendo e usando os modelos de threading do COM.
Exemplos de código
Vamos usar uma implementação de exemplo de uma classe de runtime para mostrar como o C++/WinRT dá suporte à agilidade.
#include <winrt/Windows.Foundation.h>
using namespace winrt;
using namespace Windows::Foundation;
struct MyType : winrt::implements<MyType, IStringable>
{
winrt::hstring ToString(){ ... }
};
Como não optamos por não participar, esta implementação é ágil. A estrutura base winrt::implements implementa IAgileObject e IMarshal. A implementação IMarshal usa CoCreateFreeThreadedMarshaler para fazer a coisa certa para o código herdado que não sabe sobre IAgileObject.
Esse código verifica um objeto quanto à agilidade. A chamada para IUnknown::as gera uma exceção se myimpl não for ágil.
winrt::com_ptr<MyType> myimpl{ winrt::make_self<MyType>() };
winrt::com_ptr<IAgileObject> iagileobject{ myimpl.as<IAgileObject>() };
Em vez de lidar com uma exceção, você pode chamar IUnknown::try_as em vez disso.
winrt::com_ptr<IAgileObject> iagileobject{ myimpl.try_as<IAgileObject>() };
if (iagileobject) { /* myimpl is agile. */ }
IAgileObject não tem métodos próprios, portanto, você não pode fazer muito com ele. Essa próxima variante, então, é mais típica.
if (myimpl.try_as<IAgileObject>()) { /* myimpl is agile. */ }
IAgileObject é uma interface de marcador. O simples sucesso ou fracasso ao consultar IAgileObject é tudo o que você obtém disso em termos de informação e utilidade.
Recusar o suporte a objetos agile
Você pode optar explicitamente por desabilitar o suporte a objetos ágeis passando a estrutura marcadora winrt::non_agile como parâmetro de modelo para sua classe base.
Se você derivar diretamente de winrt::implements.
struct MyImplementation: implements<MyImplementation, IStringable, winrt::non_agile>
{
...
}
Se você estiver criando uma classe de runtime.
struct MyRuntimeClass: MyRuntimeClassT<MyRuntimeClass, winrt::non_agile>
{
...
}
Não importa onde, no pacote de parâmetros variadic, o struct do marcador é exibido.
Independentemente de você desativar ou não a agilidade, você mesmo pode implementar IMarshal. Por exemplo, você pode usar o marcador winrt::non_agile para evitar a implementação de agilidade padrão e implementar o IMarshal por conta própria, talvez para dar suporte à semântica marshal-by-value.
Referências agile (winrt::agile_ref)
Se você estiver consumindo um objeto que não seja ágil, mas precisar passá-lo em algum contexto potencialmente ágil, uma opção é usar o modelo de struct winrt::agile_ref para obter uma referência ágil a uma instância de um tipo não ágil ou a uma interface de um objeto não ágil.
NonAgileType nonagile_obj;
winrt::agile_ref<NonAgileType> agile{ nonagile_obj };
Ou você pode usar a função auxiliar winrt::make_agile .
NonAgileType nonagile_obj;
auto agile{ winrt::make_agile(nonagile_obj) };
Em ambos os casos, agile agora pode ser passado livremente para um thread em um apartamento diferente e usado lá.
co_await resume_background();
NonAgileType nonagile_obj_again{ agile.get() };
winrt::hstring message{ nonagile_obj_again.Message() };
A chamada agile_ref::get retorna um proxy que pode ser usado com segurança dentro do contexto de thread no qual get é chamado.
APIs importantes
- Interface IAgileObject
- Interface IMarshal
- modelo de struct winrt::agile_ref
- modelo de struct winrt::implements
- Modelo de função winrt::make_agile
- estrutura de marcação winrt::non_agile
- função winrt::Windows::Foundation::IUnknown::as
- Função winrt::Windows::Foundation::IUnknown::try_as
Tópicos relacionados:
Windows developer