首页 > 解决方案 > C++/CX:使用 Dispatcher 访问 UI 线程不起作用

问题描述

我正在开发 UWP 应用程序,需要在非 UI 代码中使用 TextBlock 类。尝试实例化 TextBlock 对象会产生“RPC_E_WRONG_THREAD(应用程序调用了为不同线程编组的接口)”异常。根据我在 Internet 上收集的信息,我知道我应该在 UI 线程中执行我的代码。我使用了以下代码:

CoreDispatcher^ dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher;

dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler
                                                            [/* captured variables */]() {
    TextBlock ^text_block = ref new TextBlock();
    /* other code */
});

问题是,在尝试 TextBlock 实例化的那一刻,我收到了同样的异常。我究竟做错了什么?

UPD:我刚刚意识到我正在从事的项目是一个 DirectX UWP 应用程序。这是否意味着它不能直接访问UI线程?

标签: uwpc++-cx

解决方案


Get CoreWindowfromCoreWindow::GetForCurrentThread()仅在从具有关联窗口的 UI 线程调用时才有效。相反,当您在后台线程上时,您必须以不同的方式访问 UI 线程:

Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
        CoreDispatcherPriority::Normal,
        ref new Windows::UI::Core::DispatchedHandler([this]()
{
   TextBlock ^text_block = ref new TextBlock();
   /* other code */
}));

而是找到CoreWindow您的应用程序的主视图并获取其调度程序。优点是这种方法不使用GetForCurrentThread,因此您甚至可以从后台线程使用它。

当您打开应用程序的多个视图时,这将成为一个问题 - 然后每个视图都有自己的 UI 线程,因此您必须知道此操作正在修改哪个视图,以便您知道要使用哪个调度程序。在这种情况下,您可以使用CoreApplication::Views集合来枚举和访问所有应用程序视图。


推荐阅读