Agile objects in C++/WinRT

如果一个WinRT类可以被任意线程访问,这个类就是agile的。大部分的WinRT类都是agile的,除了少部分特殊的。C++/WinRT实现的类型默认都是agile的。但是在某些场景下,你希望实现一个非agile的类,让这个类的对象可以驻留在某个STA上,你所要做的是指定winrt::non_agile:

struct MyImplementation: implements<MyImplementation, IStringable, winrt::non_agile>
{
    ...
}

WinRT是基于COM的。对于COM来说,ThreadingModel = Both的类就是agile的。Understanding and Using COM Threading Models.

默认情况下,C++/WinRT实现的类会自动实现IAgileObjectIMarshal。或者在支持IAgileObject的类上使用CoCreateFreeThreadedMarshaler 来确保正确的行为。

检查一个WinRT类对象是否为agile:

winrt::com_ptr<IAgileObject> iagileobject{ myimpl.try_as<IAgileObject>() };
if (iagileobject) { /* myimpl is agile. */ }

即便一个对象不支持,但是这个对象依然可以支持IMarshal

如果一个对象不支持agile,但是又要以agile的方式使用,那么可以使用winrt::agile_ref:

NonAgileType nonagile_obj;
winrt::agile_ref<NonAgileType> agile{ nonagile_obj };
// 或者
auto agile{ winrt::make_agile(nonagile_obj) };

在另一个Apartment上使用上面定义的nonagile_obj示例;

co_await resume_background();
NonAgileType nonagile_obj_again{ agile.get() };
winrt::hstring message{ nonagile_obj_again.Message() };

winrt::agile_ref似乎是通过RoGetAgileReference来获取相应的引用的

其他

https://stackoverflow.com/questions/10111130/is-storagefolder-thread-safe

If you marshal the object (which is the correct way of moving objects between threads), then COM will do whatever is necessary to ensure thread safety. (If the object is natively thread-safe then the “whatever is necessary” reduces to a nop.) – Raymond Chen Apr 11 ‘12 at 17:59

(本篇完)