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)); } }
关键注意点:
- 必须用异步方法:如果你的SMTP代码之前用的是
Send()(同步),一定要换成SendMailAsync(),否则哪怕套了async也还是会阻塞主线程。 - 状态通知不能少:因为我们用了属性绑定,所以必须通过
OnPropertyChanged通知UI属性变化,不然IsVisible和IsRunning不会更新。要是你用MVVM框架(比如Prism、MvvmCross),可以直接继承ObservableObject来简化这部分代码。 - finally块确保提示隐藏:不管发送成功还是抛出异常,都要把
IsLoading设回false,避免加载提示一直挂着。
内容的提问来源于stack exchange,提问作者Sayo Komolafe
相关产品推荐
相关产品推荐

