2

我正在使用 WRL 将常规 C++ 应用程序移植到 C++ 中的 Metro。我有一个现有的线程池,并且在某些时候我需要从这些线程之一更新 UI。

直接触摸 UI 对象会产生预期的 RPC_E_WRONG_THREAD,因此我需要以某种方式在正确的线程中执行。查看 MSDN,我发现 Metro Dispatcher (CoreDispatcher) 有一个 RunAsync 方法。

Larry Osterman 在这里回答了如何使用它的问题: Run code on UI thread in WinRT

但不清楚的是,我是否可以从非 winrt 线程(即未调用 RoInitialize 的线程)执行此操作。

我想更准确地说,我担心调度程序可能属于 STA,我需要以某种方式编组接口,以便从我的其他线程调用是安全的。

请注意,我的应用程序在 msdn 示例之后的 main() 函数调用 RoInitialize(RO_INIT_MULTITHREADED)。

4

1 回答 1

1

您应该可以从非 UI 线程调用 CoreDispatcher::RunAsync。但有几点需要注意:1)您需要使用 Metro 风格的应用程序(这应该不言而喻)。原因是应用程序对象创建了一个在应用程序生命周期中存在的 MTA。COM 有一个称为隐式 MTA 的漂亮特性——如果 MTA 存在于您的进程中,则任何线程都被视为该 MTA 的一部分,即使它们没有调用 CoInitialize。

这意味着当您访问 CoreDispatcher::RunAsync 时,即使您需要代理对象,MTA 也是活动的,因此编组应该成功。

请注意,在应用程序启动期间有一段时间可能尚未创建应用程序对象 - 在执行应用程序代码之前,您应该避免做任何事情。

2)您需要在您要使用的 UI 线程上捕获 CoreDispatcher 对象。由于 Xaml 基础结构已经在DependencyObject中捕获了调度程序,这一点变得更加容易。因此,如果您已经拥有 Xaml UI 元素,则只需调用 .Dispatcher.RunAsync()。

PS:UI线程在ASTA(应用程序STA,Win8中新增的一种公寓)上,但是调度器是线程敏捷的。请注意,虽然调度程序是敏捷的,但不应将 CoreWindow 视为敏捷。

于 2012-05-22T05:08:54.647 回答