Win32与UWP互通信时SendMessageAsync随机抛出异常问题
解决UWP中WinForms组件调用SendMessageAsync时的InvalidOperationException问题
我之前也踩过类似的坑,结合你的场景给你几个针对性的解决方向:
1. 换掉async void的写法(事件处理除外)
你当前的SendToUWPVoidAsync用了async void,这种写法除了UI事件处理程序外,很容易导致上下文混乱、异常无法被捕获,甚至触发意外的线程切换。改成async Task会更可控:
private async Task SendToUWPAsync(object content) { ValueSet message = new ValueSet(); // 你的message填充逻辑... // 先检查连接状态再发送 if (connection?.Status == AppServiceConnectionStatus.Connected) { try { var response = await connection.SendMessageAsync(message); // 这里可以处理UWP返回的响应 } catch (Exception ex) { // 主动捕获异常,避免程序崩溃 } } else { // 连接未就绪,可做重试提示或延迟处理 } }
调用时如果是在事件里,直接用await SendToUWPAsync(content);;非事件场景要确保正确处理异步流程。
2. 等AppServiceConnection完全建立后再发消息
启动WinForms组件时,很可能AppService的连接还没完成Connected状态切换,这时候调用SendMessageAsync就会触发异常。你可以这么做:
- 监听
connection.StatusChanged事件,维护一个连接就绪的标记 - 发送消息前必须检查
connection.Status是否为AppServiceConnectionStatus.Connected - 如果是启动WinForms后立即发消息,用
TaskCompletionSource等待连接完成:
private TaskCompletionSource<bool> _connectionReadyTcs; // 初始化连接的地方 _connectionReadyTcs = new TaskCompletionSource<bool>(); connection.StatusChanged += (sender, args) => { if (args.Status == AppServiceConnectionStatus.Connected) { _connectionReadyTcs.TrySetResult(true); } else { _connectionReadyTcs.TrySetException(new InvalidOperationException("连接未建立")); } }; // 启动WinForms后要发消息时 await _connectionReadyTcs.Task; await SendToUWPAsync(content);
3. 确保在正确的线程上调用SendMessageAsync
UWP的AppServiceConnection操作需要在UI线程(或拥有CoreDispatcher的线程)上执行,要是WinForms组件在非UI线程初始化,就容易触发这个异常。可以用UWP的CoreDispatcher调度:
private async Task SendToUWPAsync(object content) { // 获取UWP主UI线程的Dispatcher var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher; await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => { ValueSet message = new ValueSet(); // 填充message... if (connection?.Status == AppServiceConnectionStatus.Connected) { var response = await connection.SendMessageAsync(message); // 处理响应 } }); }
4. 加个重试机制兜底
即使做了前面的检查,偶尔还是可能因为连接波动触发异常,加个简单的重试逻辑能提高稳定性:
private async Task<bool> SendToUWPWithRetryAsync(object content, int retryCount = 2) { for (int i = 0; i <= retryCount; i++) { try { await SendToUWPAsync(content); return true; } catch (InvalidOperationException) { if (i == retryCount) throw; // 最后一次重试失败再抛出 await Task.Delay(100); // 等待100ms后重试 } } return false; }
核心就是这几个点:确保连接就绪、避免async void、在正确线程调用、加上异常处理和重试。调整后应该就能解决这个时好时坏的异常了。
内容的提问来源于stack exchange,提问作者user9618595
相关产品推荐
相关产品推荐

