我不希望用户等待页面完成发送过程,所以我想在ASP.NET 3.5中使用SendAsync。但是在调试之后,我发现主线程仍然等待。
Main: Call send email function... mailSend: Configuring.... mailSend: setting up incorrect port.... mailSend: Attempt now to send.... mailSend: End of Line Main: Email Function call finish. Main: Proccess Complete! mailComp: Sending of mail failed, will try again in 5 seconds... mailComp: Retrying... mailComp: Send successful! mailComp: End of Line
现在我放置了错误的端口设置,因此第一封电子邮件失败,并测试第二次是否成功。即使使用正确的端口,页面仍然等待。只有在mailComp函数完成后才会最终发布Page。这是SendAsyn的一些限制吗?
这里有一些代码,不确定这是否有用。
protected void btnReset_Click(object sender, EventArgs e) { try { DataContext db = new DataContext(); var query = from u in db.Fish where u.Username == txtUsername.Text & u.Email == txtEmail.Text select new { u.Username, u.Email }; if (query.Count() != 0) { User user = new User(); String token = user.requestPasswordReset(txtUsername.Text); String URL = Request.Url.AbsoluteUri.ToString() + "?token=" + token; String body = "Reseting you password if you \n" + URL + "\n \n "; Untilty.SendEmail(txtEmail.Text, "Reseting Password", body); litTitle.Text = "Message was sent!"; litInfo.Text = "Please check your email in a few minuets for further instruction."; viewMode(false, false); } else { litCannotFindUserWithEmail.Visible = true; } } catch (Exception ex) { Debug.Write("Main: Exception: " + ex.ToString()); litInfo.Text = "We are currently having some technically difficulty. Please try again in a few minuets. If you are still having issue call us at 905344525"; } } /// public static class Utility /// public static void SendEmail(string recipient, string subject, string body) { MailMessage message = new MailMessage(); message.To.Add(new MailAddress(recipient)); message.From = new MailAddress(fromaddress, "Basadur Profile Website"); message.Subject = subject; message.Body = body; Send(message); } private static void Send(MailMessage msg) { SmtpClient smtp = new SmtpClient(); smtp.Host = "smtp.gmail.com"; smtp.Credentials = new System.Net.NetworkCredential(fromaddress, mailpassword); smtp.EnableSsl = true; Debug.WriteLine("mailSend: setting up incorrect port...."); smtp.Port = 5872; //incorrect port smtp.SendCompleted += new SendCompletedEventHandler(smtp_SendCompleted); smtp.SendAsync(msg, msg); } static void smtp_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { var msg = (MailMessage)e.UserState; if (e.Error != null) { System.Threading.Thread.Sleep(1000 * 5); try { SmtpClient smtp = new SmtpClient(); smtp.Host = "smtp.gmail.com"; smtp.Credentials = new System.Net.NetworkCredential(fromaddress, mailpassword); smtp.EnableSsl = true; smtp.Port = 587; smtp.Send(msg); } catch (Exception ex) { Debug.WriteLine("mailComp: Failed for the second time giving up."); } } }
答案 0 :(得分:3)
在.NET 4.5.2中,添加了一种方法,用于在后台安排任务,与任何请求无关:HostingEnvironment.QueueBackgroundWorkItem()。
HostingEnvironment.QueueBackgroundWorkItem()
位于System.Web.Hosting
命名空间中。
文件中的评论说:
与ASP.NET中可以保留的普通ThreadPool工作项不同 跟踪当前通过此API注册的工作项数 运行,并且ASP.NET运行时将尝试延迟AppDomain关闭 直到这些工作项目完成执行。
意思是,您可以以一种即发即忘的方式启动任务,并且在应用程序域回收时不会被终止。
用法如下:
HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
try
{
// do work....
}
catch(Exception)
{
//make sure nothing can throw in here
}
});
答案 1 :(得分:1)
现在,您可以使用Task将工作分派给线程池。只需使用
Task.Run(()=> Untilty.SendEmail(txtEmail.Text, "Reseting Password", body));
答案 2 :(得分:0)
调试器似乎强迫事物是单线程的。如果您单步执行,您可能会发现最终在两个不同的文件之间跳转,因为每个步骤移动一个不同的线程。
尝试在那里添加一些日志记录并在不调试的情况下运行。
答案 3 :(得分:0)
使用以下代码,您可以使用SmtpClient在asp.net中发送异步电子邮件。
ThreadPool.QueueUserWorkItem(callback =>
{
var mailMessage = new MailMessage
{
...
};
//if you need any references in handlers
object userState = new ReturnObject
{
MailMessage = mailMessage,
SmtpClient = smtpServer
};
smtpServer.SendCompleted += HandleSmtpResponse;
smtpServer.SendAsync(mailMessage, userState);
});
答案 4 :(得分:-2)
使用线程:
// Create the thread object, passing in the method
// via a ThreadStart delegate. This does not start the thread.
Thread oThread = new Thread(new ThreadStart(SendMyEmail));
// Start the thread
oThread.Start();
Here是源代码,它有一个完整的线程教程。