使用MAUI静态等待弹窗服务触发Cannot access a disposed object异常
问题分析与解决方案
你的认知没错:静态类和静态变量的生命周期确实会持续到应用程序退出(应用域卸载),但问题出在MAUI Community Toolkit的Popup组件本身的生命周期机制上,和静态变量是否存在无关。
异常原因
当你调用waitingPopup.Close()关闭弹窗后,MAUI框架会自动调用Popup实例的Dispose()方法,释放它内部的UI资源和绑定的上下文。此时静态变量waitingPopup虽然还在内存中(因为静态引用没被销毁),但它指向的Popup实例已经处于已释放状态,无法再被调用ShowPopupAsync()显示,第二次调用自然会抛出“无法访问已释放对象”的异常。
修复方案
有两种常用的解决思路:
方案1:检查弹窗状态,已释放则重新创建实例
修改ShowWaitingPopupAsync方法,每次显示前判断弹窗是否已被释放,若已释放则重新创建新的实例:
public static class WaitingService { private static WaitingPopup waitingPopup; async public static Task ShowWaitingPopupAsync() { try { // 若弹窗未初始化或已被释放,重新创建实例 if (waitingPopup == null || waitingPopup.IsDisposed) { waitingPopup = new WaitingPopup(); } await Application.Current.MainPage.ShowPopupAsync(waitingPopup); } catch (Exception ex) { await Application.Current.MainPage.DisplayAlert("异常", ex.Message, "确定"); } } public static void HideWaitingPopup() { waitingPopup?.Close(); } }
方案2:每次显示时创建新的Popup实例
放弃静态持有弹窗实例,每次调用ShowWaitingPopupAsync时创建新的Popup对象,这种方式更简单,无需管理实例状态:
public static class WaitingService { // 若需要手动关闭,可以返回Popup实例让调用方持有 async public static Task<WaitingPopup> ShowWaitingPopupAsync() { try { var waitingPopup = new WaitingPopup(); await Application.Current.MainPage.ShowPopupAsync(waitingPopup); return waitingPopup; } catch (Exception ex) { await Application.Current.MainPage.DisplayAlert("异常", ex.Message, "确定"); return null; } } // 调用方可以通过持有返回的实例来关闭弹窗 public static void HideWaitingPopup(WaitingPopup popup) { popup?.Close(); } }
注意
不要尝试阻止Popup自动Dispose,这会违反MAUI的组件生命周期管理规则,可能导致内存泄漏或其他UI异常。
内容的提问来源于stack exchange,提问作者XJonOneX
相关产品推荐
相关产品推荐

