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

NET8 MAUI中CommunityToolkit Popup无法正常关闭问题求助

问题描述

在.NET8 MAUI应用中,我使用CommunityToolkit的Popup服务实现了一个LoadingPopup。页面注入了ViewModel(示例用vm表示),LoadingPopup的XAML代码如下:

<toolkit:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
          x:Class="MyProject.SimplePopup">

    <VerticalStackLayout>
        <Label Text="This is a very important message!" />
    </VerticalStackLayout>
</toolkit:Popup>

页面的OnAppearing方法中调用ViewModel的初始化逻辑:

protected override async void OnAppearing()
{
    base.OnAppearing();
    await vm.Init();
}

ViewModel的Init方法代码如下:

public async Task Init()
{
    if (IsRefreshing)
        return;

    IsRefreshing = true;

    var loadingPopup = new LoadingPopup();
    Application.Current.MainPage.ShowPopup(loadingPopup);

    // step 1: 执行业务操作

    loadingPopup.Close();
    IsRefreshing = false;
}

遇到的问题:

  • 当step 1操作耗时较长时,LoadingPopup能正常显示并关闭;
  • 当step 1操作很快时,LoadingPopup会一直停留在界面,调试显示代码执行了显示和关闭逻辑,但实际无效果;
  • 改用异步方法await Application.Current.MainPage.ShowPopupAsync(loadingPopup);后,应用会一直处于等待状态。

解决方案

问题根源

  1. 同步场景下:UI线程还没完成Popup的渲染,就执行了Close操作,导致渲染和关闭逻辑在同一个UI线程周期内执行,最终Popup无法正常关闭;
  2. ShowPopupAsync使用错误:该方法会等待Popup被手动关闭后才继续执行后续代码,直接在调用后执行Close会造成阻塞,引发死等。

具体修复

1. 解决同步场景下Popup无法关闭的问题

在显示Popup后,给UI线程留出渲染时间,再执行后续业务操作:

public async Task Init()
{
    if (IsRefreshing)
        return;

    IsRefreshing = true;

    var loadingPopup = new LoadingPopup();
    Application.Current.MainPage.ShowPopup(loadingPopup);

    // 给UI线程留出渲染Popup的时间
    await Task.Delay(1);

    // step 1: 执行你的业务操作
    // 示例:await FetchDataAsync();

    loadingPopup.Close();
    IsRefreshing = false;
}

2. 正确使用ShowPopupAsync方法

将业务操作放在后台线程执行,避免阻塞UI线程和Popup的等待逻辑:

public async Task Init()
{
    if (IsRefreshing)
        return;

    IsRefreshing = true;

    var loadingPopup = new LoadingPopup();
    
    // 后台执行业务操作
    var task = Task.Run(async () =>
    {
        // step 1: 执行你的业务操作
        // 示例:await FetchDataAsync();

        // 回到UI线程关闭Popup
        await MainThread.InvokeOnMainThreadAsync(() => loadingPopup.Close());
    });

    // 等待Popup关闭
    await Application.Current.MainPage.ShowPopupAsync(loadingPopup);
    
    // 等待后台业务操作完成
    await task;
    
    IsRefreshing = false;
}

3. 封装复用(可选)

可以把LoadingPopup的显示和关闭逻辑封装成通用方法,简化调用:

public static async Task WithLoading(Func<Task> action)
{
    var loadingPopup = new LoadingPopup();
    Application.Current.MainPage.ShowPopup(loadingPopup);
    
    await Task.Delay(1);
    
    try
    {
        await action();
    }
    finally
    {
        loadingPopup.Close();
    }
}

在ViewModel中调用:

public async Task Init()
{
    if (IsRefreshing)
        return;

    IsRefreshing = true;
    
    await WithLoading(async () =>
    {
        // step 1: 执行你的业务操作
    });
    
    IsRefreshing = false;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 23:43:35