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

如何编写可被C++/WinRT调用的C# WinUI3异步代码?

解决WinUI3 C++调用C#异步代码崩溃问题

核心问题根源

你遇到的0xE0434352错误附带0x8001010E参数,本质是RPC_E_WRONG_THREAD(线程上下文不匹配)。C++/WinRT依赖Windows Runtime原生异步模型(IAsyncAction/IAsyncOperation),直接暴露C#的Task类型会导致线程调度冲突,进而触发未处理异常。

解决方案

1. 将C#异步方法转为WinRT兼容的异步类型

C++/WinRT无法直接消费Task,必须把C#方法的返回类型替换为WinRT异步接口,并用AsyncInfo.Run包装异步逻辑:

  • 无返回值操作:返回IAsyncAction
  • 有返回值操作:返回IAsyncOperation<T>(T为具体返回类型)

示例C#代码:

using Windows.Foundation;

public IAsyncAction MyAsyncOperation()
{
    return AsyncInfo.Run(async token =>
    {
        // 你的异步逻辑,这里用Task.Delay模拟
        await Task.Delay(5000, token);
        // 如需UI操作,需确保在UI线程执行
        await DispatcherQueue.GetForCurrentThread().EnqueueAsync(() =>
        {
            MyButton.Content = "异步操作完成";
        });
    });
}

2. C++侧用WinRT协程模式等待异步完成

绝对不能用Wait()/GetAwaiter().GetResult()这类同步阻塞方法,必须在C++的协程函数中用co_await等待:

示例C++代码:

#include <winrt/Windows.Foundation.h>

// 在按钮点击等协程兼容的handler中调用
winrt::IAsyncAction MyButton_ClickHandler(winrt::IInspectable const& sender, winrt::RoutedEventArgs const& e)
{
    auto myControl = sender.as<YourCSharpControl>();
    // 调用C#异步方法并等待
    co_await myControl.MyAsyncOperation();
}

3. 正确处理异常

在C#异步逻辑内部捕获异常并重新抛出,C++侧通过winrt::hresult_error接收:

C#代码:

public IAsyncAction MyAsyncOperation()
{
    return AsyncInfo.Run(async token =>
    {
        try
        {
            await Task.Delay(5000, token);
            if (someErrorCondition)
                throw new InvalidOperationException("操作失败");
        }
        catch (Exception ex)
        {
            // 可在此记录日志,再重新抛出给C++侧处理
            throw;
        }
    });
}

C++代码:

winrt::IAsyncAction MyButton_ClickHandler(winrt::IInspectable const& sender, winrt::RoutedEventArgs const& e)
{
    try
    {
        auto myControl = sender.as<YourCSharpControl>();
        co_await myControl.MyAsyncOperation();
    }
    catch (const winrt::hresult_error& ex)
    {
        // 处理异常:获取错误码和信息
        winrt::hresult errorCode = ex.code();
        winrt::hstring errorMsg = ex.message();
    }
}

4. 可选:支持异步取消

通过CancellationToken实现跨语言的取消逻辑:

C#代码:

public IAsyncAction MyAsyncOperation(CancellationToken cancelToken)
{
    return AsyncInfo.Run(async ct =>
    {
        // 绑定WinRT和C#的取消令牌
        using var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancelToken, ct).Token;
        await Task.Delay(5000, linkedToken);
    });
}

C++代码:

winrt::IAsyncAction MyButton_ClickHandler(winrt::IInspectable const& sender, winrt::RoutedEventArgs const& e)
{
    winrt::CancellationTokenSource cts;
    auto myControl = sender.as<YourCSharpControl>();
    auto action = myControl.MyAsyncOperation(cts.Token());
    
    // 如需取消:cts.Cancel();
    co_await action;
}

内容的提问来源于stack exchange,提问作者Biff MaGriff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 03:28:17