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

Uno Platform Xamarin Forms WASM连续调用DisplayPromptAsync卡死及报错问题

问题成因
  • 核心问题是Uno Platform WASM端的ContentDialog实现存在状态竞争缺陷:
    • 你贴的堆栈已经明确显示,点击第一个弹窗OK按钮时,ContentDialog.ProcessPrimaryButton逻辑里会对已经完成状态的TaskCompletionSource重复调用SetResult,抛出InvalidOperationException
    • 这个异常发生在PointerReleased事件的同步触发管道中,没有被Uno的事件系统全局捕获兜底,直接打断了UI线程的消息循环分发流程
    • 流程中断后,第二次调用DisplayPromptAsync时,UI线程已经无法正常处理弹窗的渲染、交互请求,最终表现为Web应用完全卡死
  • 该问题在原生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线程强绑定,跨线程调用会触发更严重的线程访问异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 18:15:02