WinRT: приложение вызвало интерфейс, который был назначен для другого потока - PullRequest
0 голосов
/ 09 апреля 2020

Я знаю, когда появится эта информация об ошибке. В с ++ / cx раньше это работало. Но в c ++ / winrt это проблема с маршалингом.

Я пытаюсь создать некоторые таймеры из моего метода init.

Метод инициализации:

void App::InitAsync()
{
    concurrency::create_task([this]
        {
            //Do my stuffs
        }).then([this](concurrency::task<void> task)
            {
                try
                {
                    task.get();
                }
                catch (const std::exception& /*e*/)
                {
                }
                m_timer = CreateAndStartDispatcherTimer(500ms, &App::OnTimerTick);

            }, concurrency::task_continuation_context::use_default());
}

Метод создания таймера :

Windows::UI::Xaml::DispatcherTimer App::CreateAndStartDispatcherTimer(std::chrono::milliseconds interval, void(App::* onTick)(IInspectable sender, IInspectable e))
{
    auto timer{ DispatcherTimer() }; // the exception is thrown from here
    timer.Tick(EventHandler<IInspectable>(this, onTick));
    timer.Interval(interval);
    timer.Start();
    return timer;
}

Пожалуйста, подскажите, как я могу заставить его работать. Для воспроизведения я загрузил решение здесь .

1 Ответ

0 голосов
/ 10 апреля 2020

Приложение вызвало интерфейс, который был назначен для другого потока

Это исключение означает, что ваша функция касается пользовательского интерфейса приложения, а затем должна быть запущена в потоке диспетчера пользовательского интерфейса. Таким образом, вы можете co_await функцию winrt :: resume_foreground , чтобы переключиться на указанный c поток переднего плана. Например:

#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.ApplicationModel.Core.h>

{
    ......
    CreateAndStartDispatcherTimer(yourInterval);
}

Windows::Foundation::IAsyncAction winrt::AsyncAppWinrt::implementation::App::CreateAndStartDispatcherTimer(std::chrono::milliseconds interval)
{
    co_await winrt::resume_foreground(Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher());

    m_timer = Windows::UI::Xaml::DispatcherTimer();
    m_timer.Interval(interval);
    auto registrationtoken = m_timer.Tick({ this, &App::OnTick });
    m_timer.Start();
}

Для получения дополнительной информации об этом вы можете обратиться к этому документу: Более продвинутый параллелизм и асинхронность с C ++ / WinRT

...