Uno Platform Xamarin Forms WASM连续调用DisplayPromptAsync卡死及报错问题
问题成因
- 核心问题是Uno Platform WASM端的ContentDialog实现存在状态竞争缺陷:
- 你贴的堆栈已经明确显示,点击第一个弹窗OK按钮时,
ContentDialog.ProcessPrimaryButton逻辑里会对已经完成状态的TaskCompletionSource重复调用SetResult,抛出InvalidOperationException - 这个异常发生在
PointerReleased事件的同步触发管道中,没有被Uno的事件系统全局捕获兜底,直接打断了UI线程的消息循环分发流程 - 流程中断后,第二次调用
DisplayPromptAsync时,UI线程已经无法正常处理弹窗的渲染、交互请求,最终表现为Web应用完全卡死
- 你贴的堆栈已经明确显示,点击第一个弹窗OK按钮时,
- 该问题在原生UWP上不会复现,是因为UWP原生ContentDialog会在按钮点击事件的所有冒泡流程完全结束后,才会异步设置弹窗的返回结果,从实现层面避免了同事件周期内重复触发结果设置的问题。
适配代码调整方案
- 临时可落地的规避逻辑核心是:将第二次弹窗的触发时机,延后到第一次弹窗的所有UI事件流程完全结束之后,从同步上下文上把两次弹窗的调用隔离开。
- 调整后的兼容代码示例:
private async void Button_Clicked(object sender, EventArgs e) { var response1 = await App.Current.MainPage.DisplayPromptAsync("", "message1", "OK", "Cancel", ""); if (string.IsNullOrEmpty(response1)) return; // 主动让出UI线程执行权,等待第一次弹窗的事件冒泡、状态清理全部完成 await Task.Yield(); var response2 = await App.Current.MainPage.DisplayPromptAsync("", "message2", "OK", "Cancel", ""); if (string.IsNullOrEmpty(response2)) return; }
- 优化建议:
- 如果项目使用的Uno.UI版本低于4.9,建议升级到最新稳定版,该版本对ContentDialog的按钮点击结果逻辑做了异常包裹,不会再出现重复设置结果打断UI线程管道的问题,升级后即使不插入
Task.Yield()也能正常运行连续弹窗逻辑 - 不要通过
Task.Run之类的跨线程调用触发弹窗,ContentDialog的状态和UI线程强绑定,跨线程调用会触发更严重的线程访问异常。
- 如果项目使用的Uno.UI版本低于4.9,建议升级到最新稳定版,该版本对ContentDialog的按钮点击结果逻辑做了异常包裹,不会再出现重复设置结果打断UI线程管道的问题,升级后即使不插入
内容的提问来源于stack exchange,提问作者trungnt2910
相关产品推荐
相关产品推荐

