基于Desktop Bridge与Windows App SDK的WinUI3内购报错:需从UI线程调用
解决WinUI 3桌面应用内购买的UI线程错误问题
核心问题原因
错误0x80070578 : 'This function must be called from a UI thread'的触发原因主要有两点:
- 基于Desktop Bridge打包的WinUI 3桌面应用中,
StoreContext未正确关联当前UI窗口,导致系统无法识别调用的UI线程上下文。 - 直接同步调用异步购买方法,未正确处理WinRT异步操作的线程调度逻辑。
具体解决方案
1. 正确关联StoreContext到当前UI窗口
桌面应用与UWP不同,需要将StoreContext绑定到当前窗口的HWND,确保系统能识别UI线程上下文:
#include <winrt/Windows.Services.Store.h> #include <Microsoft.UI.Xaml.Hosting.h> #include <Windows.h> HWND GetCurrentWindowHandle() { auto currentWindow = winrt::Microsoft::UI::Xaml::Window::Current(); auto windowInterop = currentWindow.as<::IWindowNative>(); HWND hwnd = nullptr; windowInterop->get_WindowHandle(&hwnd); return hwnd; }
在购买方法中,使用GetForWindow获取绑定当前窗口的StoreContext:
winrt::Windows::Services::Store::StoreContext storeContext = winrt::Windows::Services::Store::StoreContext::GetForWindow(GetCurrentWindowHandle());
2. 使用协程处理异步购买操作
将按钮点击事件和购买方法改为协程(fire_and_forget),确保异步操作始终在UI线程调度:
- 修改按钮点击事件:
#include <winrt/Windows.Foundation.h> winrt::fire_and_forget MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&) { auto transactionService = std::make_unique<TransactionService>(); co_await transactionService->buyOrRestore(); }
- 修改
TransactionService的购买方法:
class TransactionService { public: winrt::fire_and_forget buyOrRestore() { try { // 获取绑定当前窗口的StoreContext auto hwnd = GetCurrentWindowHandle(); auto storeContext = winrt::Windows::Services::Store::StoreContext::GetForWindow(hwnd); // 配置购买属性 winrt::Windows::Services::Store::StorePurchaseProperties purchaseProperties; purchaseProperties.Name(L"你的商品名称"); // 异步调用购买接口 auto purchaseResult = co_await storeContext.RequestPurchaseWithPurchasePropertiesAsync( winrt::hstring(kItemStoreId), purchaseProperties); // 处理购买结果 switch (purchaseResult.Status()) { case winrt::Windows::Services::Store::StorePurchaseStatus::Succeeded: // 购买成功逻辑 break; case winrt::Windows::Services::Store::StorePurchaseStatus::AlreadyPurchased: // 已购买,执行恢复逻辑 break; case winrt::Windows::Services::Store::StorePurchaseStatus::NotPurchased: // 用户取消购买 break; default: // 其他错误情况 break; } } catch (const winrt::hresult_error& ex) { // 捕获并处理错误 auto errorMsg = ex.Message(); // 可添加错误提示逻辑 } } private: HWND GetCurrentWindowHandle() { auto currentWindow = winrt::Microsoft::UI::Xaml::Window::Current(); auto windowInterop = currentWindow.as<::IWindowNative>(); HWND hwnd = nullptr; windowInterop->get_WindowHandle(&hwnd); return hwnd; } };
3. 项目配置检查
确保项目已添加必要依赖:
- 包含头文件:
Microsoft.UI.Xaml.Hosting.h、winrt/Windows.Services.Store.h - 链接库:在项目属性→链接器→输入→附加依赖项中添加
windowsapp.lib
关键注意点
- 禁止直接同步调用WinRT异步方法,必须通过
co_await处理,避免线程上下文丢失。 - 桌面应用中
StoreContext必须绑定当前窗口HWND,否则无法正确识别UI线程。 - 始终捕获
hresult_error异常,处理购买过程中的各类错误场景。
内容的提问来源于stack exchange,提问作者JaSHin
相关产品推荐
相关产品推荐

