.NET MAUI弹窗CloseAsync()无法完成任务求助
弹窗关闭异步任务未完成及CancellationToken异常问题解决
问题场景
尝试用PopupService实现带参数传递和返回值的弹窗,但关闭弹窗时异步任务始终无法完成。手动添加CancellationToken并设置超时后,又抛出System.Threading.Tasks.TaskCanceledException: 'A task was canceled.'异常。
相关代码
调用弹窗的ViewModel
public partial class SomeViewModel { private readonly IPopupService _popupService; // ... public SomeViewModel( IPopupService popupService) { _popupService = popupService; } [RelayCommand] private async Task OnCallingPopUpAsync() { var result = await _popupService.ShowPopupAsync<PopupViewModel>( onPresenting: viewModel => viewModel.TransferValue(true) ); if (result is bool boolResult) Debug.WriteLine("Success!!"); else return; } }
弹窗ViewModel
public partial class PopupViewModel : Popup { // 原代码构造函数存在笔误 public ImagePickerViewModel() {} [RelayCommand] private async Task OnClosePopup() { await CloseAsync(true); } public void TransferValue(bool value) { Debug.WriteLine($"The transferred value is {value}"); } }
错误的CancellationToken尝试代码
[RelayCommand] private async Task OnClosePopup() { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1)); await CloseAsync(true, token: cts.Token); }
问题分析
- 弹窗无法关闭核心原因:首先是弹窗ViewModel的构造函数存在笔误(
ImagePickerViewModel()应为PopupViewModel()),导致ViewModel实例化异常;其次,PopupService的ShowPopupAsync可能未正确监听弹窗关闭事件,无法完成异步任务;另外,CloseAsync的调用未正确关联弹窗生命周期。 - CancellationToken异常原因:手动设置1秒超时的CancellationTokenSource会强制取消任务,这不是正常关闭弹窗的正确方式,自然会抛出取消异常。
解决步骤
1. 修正弹窗ViewModel的构造函数笔误
把错误的构造函数改为正确的类名:
public partial class PopupViewModel : Popup { public PopupViewModel() {} // 其他代码不变 }
2. 移除手动添加的CancellationToken
正常关闭弹窗不需要手动设置超时取消,直接调用CloseAsync传入返回值即可:
[RelayCommand] private async Task OnClosePopup() { await CloseAsync(true); }
3. 确认PopupService的调用逻辑(以CommunityToolkit.Maui为例)
如果使用的是CommunityToolkit.Maui的IPopupService,确保调用方式正确,弹窗ViewModel和视图的生命周期绑定正常:
[RelayCommand] private async Task OnCallingPopUpAsync() { // 实例化弹窗ViewModel并传参 var popupVm = new PopupViewModel(); popupVm.TransferValue(true); // 直接传入ViewModel实例调用ShowPopupAsync var result = await _popupService.ShowPopupAsync(popupVm); if (result is bool boolResult) Debug.WriteLine("Success!!"); }
4. 排查视图绑定和弹窗生命周期
- 检查弹窗XAML中的关闭按钮是否正确绑定
ClosePopupCommand,确保点击事件能触发命令:<Button Text="关闭" Command="{Binding ClosePopupCommand}" /> - 如果是自定义PopupService,检查
ShowPopupAsync方法是否在弹窗关闭时,通过TaskCompletionSource.SetResult(result)完成异步任务,确保调用方的await能收到返回值并结束任务。
内容的提问来源于stack exchange,提问作者user25033240
相关产品推荐
相关产品推荐

