为什么 `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,它会让您进入正确的线程。然后您可以直接调用对象上的方法。
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,它会让您进入正确的线程。然后您可以直接调用对象上的方法。