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

Xamarin应用SMTP发邮件时ActivityIndicator不显示问题求助

嘿,我完全懂你遇到的糟心事——点击发送邮件后,APP就僵在那儿,加载提示啥的全不出来,用户根本不知道后台在干活对吧?这问题十有八九是你在UI主线程里同步执行了SMTP发送操作,把主线程堵死了,导致ActivityIndicator和Label的状态更新根本没法生效。

下面给你一套具体的修复方案,分XAML和代码后台两部分来调整:

第一步:调整XAML,让加载提示绑定状态

先把你的加载区域改成绑定式的,这样状态变化时UI能自动响应:

<StackLayout x:Name="myPop">
    <!-- 这里放你原来的表单输入控件 -->
    
    <!-- 提交按钮 -->
    <Button Text="发送邮件" Clicked="OnSendEmailClicked" 
            Margin="0,20,0,0" HorizontalOptions="Fill"/>

    <!-- 加载提示区域,默认隐藏 -->
    <StackLayout IsVisible="{Binding IsLoading}" 
                 HorizontalOptions="Center" VerticalOptions="Center"
                 Margin="0,20,0,0">
        <ActivityIndicator IsRunning="{Binding IsLoading}" 
                           Color="#2196F3" HeightRequest="40" WidthRequest="40"/>
        <Label Text="正在发送邮件,请稍候..." 
               Margin="0,10,0,0" FontSize="Small"/>
    </StackLayout>
</StackLayout>

第二步:异步处理邮件发送,解放UI线程

在你的ContentPage代码后台,用async/await异步执行发送逻辑,同时控制加载状态:

using System.ComponentModel;
using System.Net;
using System.Net.Mail;
using System.Threading.Tasks;
using Xamarin.Forms;

public class YourEmailPage : ContentPage, INotifyPropertyChanged
{
    private bool _isLoading;
    public bool IsLoading
    {
        get => _isLoading;
        set
        {
            _isLoading = value;
            OnPropertyChanged(nameof(IsLoading)); // 通知UI更新状态
        }
    }

    public YourEmailPage()
    {
        InitializeComponent();
        BindingContext = this; // 把页面自身设为绑定上下文
    }

    // 按钮点击事件必须标记为async
    private async void OnSendEmailClicked(object sender, EventArgs e)
    {
        // 显示加载提示
        IsLoading = true;

        try
        {
            // 异步执行邮件发送,一定要用SMTP的异步方法!
            await SendEmailAsync();
            
            // 发送成功后弹出提示
            await DisplayAlert("成功", "邮件已顺利发送!", "确定");
        }
        catch (Exception ex)
        {
            // 捕获异常并提示用户
            await DisplayAlert("发送失败", $"出错啦:{ex.Message}", "确定");
        }
        finally
        {
            // 不管成功失败,都要隐藏加载提示
            IsLoading = false;
        }
    }

    // 封装异步的邮件发送方法
    private async Task SendEmailAsync()
    {
        using var smtpClient = new SmtpClient("你的SMTP服务器地址", 587)
        {
            Credentials = new NetworkCredential("你的邮箱账号", "授权码/密码"),
            EnableSsl = true // 大部分SMTP服务器需要开启SSL
        };

        var mailMessage = new MailMessage(
            from: "你的发件邮箱",
            to: "收件人邮箱",
            subject: "邮件主题",
            body: "邮件内容"
        );

        // 用异步方法发送,绝对不要用同步的Send()!
        await smtpClient.SendMailAsync(mailMessage);
    }

    // 实现INotifyPropertyChanged接口的必要方法
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

关键注意点:

  1. 必须用异步方法:如果你的SMTP代码之前用的是Send()(同步),一定要换成SendMailAsync(),否则哪怕套了async也还是会阻塞主线程。
  2. 状态通知不能少:因为我们用了属性绑定,所以必须通过OnPropertyChanged通知UI属性变化,不然IsVisible和IsRunning不会更新。要是你用MVVM框架(比如Prism、MvvmCross),可以直接继承ObservableObject来简化这部分代码。
  3. finally块确保提示隐藏:不管发送成功还是抛出异常,都要把IsLoading设回false,避免加载提示一直挂着。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:43:05