【问题标题】:How to call CanvasBitmap::LoadAsync properly in C++/WinRT Win2D application如何在 C++/WinRT Win2D 应用程序中正确调用 CanvasBitmap::LoadAsync
【发布时间】:2021-06-02 15:59:59
【问题描述】:

在我的 WinUI3(C++/WinRT) 应用程序中,我有一个 Win2D CanvasControl,我想在其中绘制图像。它在画布初始化时使用CanvasBitmap::LoadAsync() 加载。我很难使用 C++ 协程让它工作。

相关代码如下。

// MainWindow.xaml
<Window>
  <Grid>
    <canvas:CanvasControl x:Name="mainCanvas"Draw="mainCanvas_Draw" CreateResources="mainCanvas_CreateResources"/>
  </Grid>
</Window>
// MainWindow.xaml.cpp
MainWindow::MainWindow()
{
    InitializeComponent();

    // Sprite is a custom class and pSprite is a unique_ptr in the MainWindow class
    pSprite = std::make_unique<Sprite>(float2{ 300.0f, 300.0f }, 50.0f, 60.0f);
}

void MainWindow::mainCanvas_Draw(const CanvasControl& sender, const CanvasDrawEventArgs& args)
{
    pSprite->Update();
    pSprite->Draw(args, spriteBitmap);
}

void MainWindow::mainCanvas_CreateResources(CanvasControl const& sender, winrt::Microsoft::Graphics::Canvas::UI::CanvasCreateResourcesEventArgs const& args)
{
    args.TrackAsyncAction(CreateResourcesAsync(sender));
}

IAsyncAction MainWindow::CreateResourcesAsync(CanvasControl const& sender)
{
    // spriteBitmap is a member variable of MainWindow class
    spriteBitmap = co_await CanvasBitmap::LoadAsync(sender, Uri(L"ms-appx:///Assets/sprite.png"));
}

当我使用上面的代码运行应用程序时,会引发异常并且消息是“应用程序调用了为不同线程编组的接口。”。

非常感谢有关如何在 WinUI (C++/WinRT) 中处理异步操作的指导!

【问题讨论】:

  • 什么不起作用?预期的行为是什么?观察到的行为是什么?您绝对需要解决的一件事是摆脱 const 引用。您需要将参数按值传递到协程中。如果你不这样做,你会得到悬空指针。
  • @IInspectable 我编辑了这个问题。我希望看到画布控件中显示的位图,但会抛出异常。
  • 我发现了类似的报告异常here。您可以参考 CoreDispatcher.RunAsync() method 中的更新 UI。
  • 我确实记得位图对它们所使用的线程非常特别。它总是必须是创建位图的同一个线程。那是当时的SoftwareBitmap,我从来没有完全理解它的线程亲和力。也许Win2D是类似的。尝试在其返回的可等待对象中使用 get() 方法阻止 LoadAsync 调用。

标签: c++-winrt win2d winui-3


【解决方案1】:

在 CreateResourcesAsync 中按值传递发件人

IAsyncAction MainWindow::CreateResourcesAsync(CanvasControl const sender)

因为 mainCanvas_CreateResources() 不等待 CreateResourcesAsync() 完成,然后在 mainCanvas_CreateResources() 退出后原来的“sender”会被销毁,所以在 CreateResourcesAsync() 中不能引用原来的“sender”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    • 2012-10-22
    • 1970-01-01
    • 2020-08-06
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多