You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Desktop Bridge与Windows App SDK的WinUI3内购报错:需从UI线程调用

解决WinUI 3桌面应用内购买的UI线程错误问题

核心问题原因

错误0x80070578 : 'This function must be called from a UI thread'的触发原因主要有两点:

  1. 基于Desktop Bridge打包的WinUI 3桌面应用中,StoreContext未正确关联当前UI窗口,导致系统无法识别调用的UI线程上下文。
  2. 直接同步调用异步购买方法,未正确处理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:15:45