C ++ / CX: использование Dispatcher для доступа к потоку пользовательского интерфейса не работает - PullRequest
0 голосов
/ 21 декабря 2018

Я работаю над приложением UWP и мне нужно использовать класс TextBlock в коде, не являющемся пользовательским интерфейсом.Попытка создания экземпляра объекта TextBlock выдает исключение «RPC_E_WRONG_THREAD (приложение вызвало интерфейс, который был назначен для другого потока)».Из информации, которую я собрал в Интернете, я понимаю, что должен выполнить свой код в потоке пользовательского интерфейса.Я использовал следующий код:

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.Означает ли это, что он не может получить доступ к потоку пользовательского интерфейса напрямую?

1 Ответ

0 голосов
/ 24 декабря 2018

Получение CoreWindow из CoreWindow::GetForCurrentThread() будет работать только при вызове из потока пользовательского интерфейса, с которым связано окно.Вместо этого, когда вы находитесь в фоновом потоке, вы должны получить доступ к потоку пользовательского интерфейса по-другому:

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, поэтому вы можете использовать его даже из фонового потока.

Это становится проблемой, когда у вас открыто несколько представлений вашего приложения - тогда каждое представлениеимеет собственный поток пользовательского интерфейса , поэтому вы должны знать, какое представление модифицирует это действие, чтобы вы знали, какой диспетчер вы хотите использовать.В этом сценарии вы можете использовать коллекцию CoreApplication::Views для перечисления и доступа ко всем представлениям приложения.

...