执行方法时表单冻结

本文关键字:冻结 表单 方法 执行 | 更新日期: 2023-09-27 18:33:45

我有我写的这个方法,当用户按下按钮时发送电子邮件。现在我面临的问题是,每当用户按下按钮时,表单都会冻结几秒钟,然后发送电子邮件。所以该方法有效,但我不明白为什么表单冻结。

string emailAddress = tbEmailAddress.Text + cbEmailAddress.Text;
string emailPassword = tbEmailPassword.Text;
string emailRecipient = tbEmailRecipient.Text;
string emailSubject = tbEmailSubject.Text;
string emailBody = rtbEmailBody.Text;
string smtpHost;
string smtpPort;
MailMessage email = new MailMessage(emailAddress, emailRecipient);
email.Subject = emailSubject;
email.Body = emailBody;
SmtpClient smtp = new SmtpClient("smtp.live.com", 587);
smtp.EnableSsl = true;
smtp.Credentials = new System.Net.NetworkCredential(emailAddress, emailPassword);
smtp.Send(email);
smtp.Dispose();

有什么方法可以解决我面临的这个问题吗?

提前谢谢你。

执行方法时表单冻结

窗体冻结,因为该方法需要在返回控件之前完成,并且发送邮件需要一些时间。可以异步运行该方法。

如果您使用的是 .NET Framework 4.5 和 C# 5,则可以使用 async-await 来实现所需的目标。否则,您可以使用 Parallel.Invoke(() => { SendMail()}), 异步运行邮件发送,也可以启动另一个线程来执行相同的操作。

您可能还想看看:在 C# 中异步发送 System.Net.Mail.MailMessage 以及相关文章:在 C# 中异步发送电子邮件?

您可以在另一个线程上调用该方法,请尝试使用 Thread 或 Task。它冻结是因为 UI 线程被任务线程阻止,因此你可以分离线程以让 UI 继续响应。

System.Threading.Thread execute = new System.Threading.Thread(delegate() 
{ /* execute method here here */ });

只是另一个解决方案..我觉得更好。任务是专门为帮助您管理此类事情而设计的。无需担心线程管理。它还允许您监视线程何时完成执行。

如果将代码包装到其自己的方法中,则可以执行以下操作:

var sendEmailTask = Task.Run(() => yourSendEmailMethod())
                            .ContinueWith(t => MessageBox.Show("Email sent"));

如前所述,问题是因为您的应用程序在单个线程上运行。在发送电子邮件期间,该线程将被阻止。如果您创建一个新线程(我的示例使用任务来执行此操作),则将使用该线程发送电子邮件。并且您的应用程序 UI 将继续在其自己的线程上运行。

使用 SmtpClient.SendMailAsync

async Task SendMail()
{
    var email = CreateMailMessage();
    using (var smtp = new SmtpClient("smtp.live.com", 587) { 
          EnableSsl = true,
          Credentials = new NetworkCredential(emailAddress, emailPassword)
        })
    {
        await smtp.SendMailAsync(email);
    }
}

表单冻结,因为您正在使用程序的默认线程发送电子邮件。应用中的所有窗口用于处理窗口事件的同一线程。当您发送电子邮件时,窗口无法处理任何 Windows 邮件。将电子邮件发送到后台线程中,然后您的应用就不会被阻止。