如何编写可被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
相关产品推荐
相关产品推荐

