为什么 `agile_ref` 对某些对象失败,例如 `CoreWindow`?

Why does `agile_ref` fail with some objects, such as `CoreWindow`?

C++/WinRT 的 agile_ref 据说允许以敏捷方式使用非敏捷对象。 但是,我发现至少 CoreWindow 个实例失败了。

举个简短的例子:

void Run()
{
    auto window{ CoreWindow::GetForCurrentThread() };
    window.Activate();

    auto agile_wnd{ make_agile(window) };
    ThreadPool::RunAsync([=](const auto&) {
        auto other_wnd{ agile_wnd.get() };
        other_wnd.SetPointerCapture();
    });

    auto dispatcher{ window.Dispatcher() };
    dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit);
}

Run() 在 UI 线程上调用,然后尝试创建一个敏捷引用,然后使用它从线程池中调用 CoreWindow。然而,这失败了 "The application called an interface that was marshaled for a different thread." 因为 agile_ref 在内部使用 RoGetAgileReference 来编组对象,并且创建引用然后解组它的调用都成功了,这在我看来是 CoreWindow 根本拒绝编组。

当然,除非这按预期工作并且 RoGetAgileReference 调用静默地无法编组 CoreWindow

那么是什么导致 SetPointerCapture 调用失败,即使 agile_ref

该错误具有误导性。大多数 Windows.UI 类 实际上是敏捷的。挑战在于它们执行显式线程检查以确保您实际上是从适当的 UI 线程调用它们。这就是 agile_ref 无济于事的原因。解决方案是使用 Dispatcher,它会让您进入正确的线程。然后您可以直接调用对象上的方法。