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

.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);
}

问题分析

  1. 弹窗无法关闭核心原因:首先是弹窗ViewModel的构造函数存在笔误(ImagePickerViewModel()应为PopupViewModel()),导致ViewModel实例化异常;其次,PopupService的ShowPopupAsync可能未正确监听弹窗关闭事件,无法完成异步任务;另外,CloseAsync的调用未正确关联弹窗生命周期。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 14:50:58