我写的这个方法是当用户按下按钮时发送电子邮件。现在我面临的问题是,每当用户按下按钮时,表单会冻结几秒钟然后发送电子邮件。所以这种方法很有效,但我不明白为什么表格冻结了。
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();
有没有办法解决我面临的这个问题?
提前谢谢。
答案 0 :(得分:4)
表单冻结是因为该方法需要在返回控件之前完成并且发送邮件需要一些时间。您可以异步运行该方法。
如果您使用的是.NET Framework 4.5和C#5,则可以使用async-await来实现您的目标。否则,您可以使用Parallel.Invoke(() => { SendMail()}),
异步运行邮件发送,或启动另一个线程来执行相同操作。
您可能还想查看:Asynchronously sending a System.Net.Mail.MailMessage in C#以及相关帖子:Asynchronously sending Emails in C#?
答案 1 :(得分:1)
只是另一种解决方案......我发现它好多了。任务专门用于帮助您管理此类事情..而不用担心线程管理。它还允许您监视线程何时完成执行。
如果将代码包装到自己的方法中,您将能够执行以下操作:
var sendEmailTask = Task.Run(() => yourSendEmailMethod())
.ContinueWith(t => MessageBox.Show("Email sent"));
如前所述,问题是因为您的应用程序在单个线程上运行。在发送电子邮件期间,该线程将被阻止。如果您创建一个新线程(我的示例使用任务来执行此操作),将使用该线程发送电子邮件..并且您的应用程序UI将继续在其自己的线程上运行。
答案 2 :(得分:1)
您应该使用SmtpClient.SendMailAsync
(.NET 4.5)或SendAsync
:
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);
}
}
答案 3 :(得分:0)
由于您使用程序的默认线程发送电子邮件,因此表单会冻结。应用程序中所有窗口使用的相同线程来处理Windows事件。在您发送电子邮件时,Windows无法处理任何Windows消息。将电子邮件发送到后台主题,然后您的应用程序将被阻止。
答案 4 :(得分:0)
您可以在另一个Thread上调用该方法,尝试使用Thread或Task。它是冻结的,因为你的任务线程阻止了UI线程,所以你可以分离线程让UI继续响应。
System.Threading.Thread execute = new System.Threading.Thread(delegate()
{ /* execute method here here */ });