执行方法时表单冻结
本文关键字:冻结 表单 方法 执行 | 更新日期: 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 邮件。将电子邮件发送到后台线程中,然后您的应用就不会被阻止。