【发布时间】: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调用。