C# 执行后端电子邮件进程,而不让用户等待它完成
在我的C# 执行后端电子邮件进程,而不让用户等待它完成,c#,asp.net-mvc,asp.net-mvc-4,c#-4.0,async-await,C#,Asp.net Mvc,Asp.net Mvc 4,C# 4.0,Async Await,在我的MVC应用程序中,我有一个功能,可以通过客户向各自的所有者/经销商发送消息。消息模型如下所示: public class Messages { public string MessageFrom { get; set; } public string MessageUserEmailID { get; set; } public string MessageUserContactNum { get; set; } public string Message { ge
MVC
应用程序中,我有一个功能,可以通过客户向各自的所有者/经销商发送消息。消息模型如下所示:
public class Messages
{
public string MessageFrom { get; set; }
public string MessageUserEmailID { get; set; }
public string MessageUserContactNum { get; set; }
public string Message { get; set; }
public int UserID { get; set; }//Admin user id
public string propertyName { get; set; }
}
public void NotifyUser(string toAddress, string userPhoneNum, string propertyName, string userMessage, string userName, string userContactEmail, string subject)
{
using (MailMessage mail = new MailMessage())
{
string Password = WebConfigurationManager.AppSettings["ApplicationEmailPassword"];
var securePassword = new SecureString();
Array.ForEach(Password.ToArray(), securePassword.AppendChar);
securePassword.MakeReadOnly();
mail.To.Add(toAddress);
mail.From = new MailAddress(WebConfigurationManager.AppSettings["ApplicationEmailID"]);
mail.Subject = subject;
mail.Body = Convert.ToString(ConstructBody(userMessage, propertyName, userPhoneNum, userContactEmail, userName));
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.UseDefaultCredentials = false;
smtp.EnableSsl = true;
smtp.Credentials = new NetworkCredential(Convert.ToString(mail.From), securePassword);
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.Send(mail);
}
}
下面是我的Controller
方法,它将通过AJAX
where调用
- 我将消息存储在数据库中
- 通过电子邮件向管理员发送通知
- 将
Json
响应返回给用户
HomeController
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SendMessage([Bind(Prefix = "messageModel")]Messages model)
{
private SendNotification notify = new SendNotification();
if (ModelState.IsValid)
{
using (db)
{
tblMessage messageModel = new tblMessage();
//....
//....
//....
//fill the messageModel with the model values
db.tblMessages.Add(messageModel);
db.SaveChanges();
string toAddress = db.tblUsers.Where(u => u.UserId == model.UserID).Select(x => x.UserEmailID).FirstOrDefault();
if (!string.IsNullOrEmpty(toAddress))
{
notify.NotifyUser(toAddress, model.MessageUserContactNum, model.propertyName, model.Message, model.MessageFrom, model.MessageUserEmailID, "Kemmale Engineers' Notification - You have a message");
}
return Json(new { result = true, message = "Message sent! Thank you! We will get back to you soon!" }, JsonRequestBehavior.AllowGet);
}
}
return Json(new { result = false, message = "Server issue! Please try again later" }, JsonRequestBehavior.AllowGet);
}
SendNotification
类包含NotifyUser
方法,如下所示:
public class Messages
{
public string MessageFrom { get; set; }
public string MessageUserEmailID { get; set; }
public string MessageUserContactNum { get; set; }
public string Message { get; set; }
public int UserID { get; set; }//Admin user id
public string propertyName { get; set; }
}
public void NotifyUser(string toAddress, string userPhoneNum, string propertyName, string userMessage, string userName, string userContactEmail, string subject)
{
using (MailMessage mail = new MailMessage())
{
string Password = WebConfigurationManager.AppSettings["ApplicationEmailPassword"];
var securePassword = new SecureString();
Array.ForEach(Password.ToArray(), securePassword.AppendChar);
securePassword.MakeReadOnly();
mail.To.Add(toAddress);
mail.From = new MailAddress(WebConfigurationManager.AppSettings["ApplicationEmailID"]);
mail.Subject = subject;
mail.Body = Convert.ToString(ConstructBody(userMessage, propertyName, userPhoneNum, userContactEmail, userName));
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.UseDefaultCredentials = false;
smtp.EnableSsl = true;
smtp.Credentials = new NetworkCredential(Convert.ToString(mail.From), securePassword);
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.Send(mail);
}
}
正如您所看到的,Notify
具有返回类型void
。既然让用户等待与用户无关的内部流程完成是非常过时的做法,那么我如何在不等待Notify
方法执行的情况下将Json
消息返回给用户呢?我正在考虑异步任务
,但不确定如何在这里实现它。如果要执行函数而不是等待它完成,那么必须在另一个线程中运行它
最简单的方法是使用任务功能
在FW4.5或更高版本中,您可以使用
Task.Run(ActionToExecute)
或者如果您使用的是FW4.0,则可以使用
Task.Factory.StartNew(ActionToExecute).
除此之外,您还可以使用线程池以老式的方式执行此操作:
ThreadPool.EnqueueUserWorkItem(ActionToExecute, null);
但是在这种情况下,操作必须有一个对象参数(即使它被忽略)。Task.Run(()=>notify.NotifyUser(…)@古斯曼。。你能详细说明一下吗?呃。。。不,没有什么需要详细说明的,只需在notify.NotifyUser调用周围加上lambda并将其传递给Task.Run,它将在另一个线程中运行,响应将立即生效,而无需等待邮件sending@Gusman. 非常感谢。实现了它,但由于我使用.netframework4
我不得不使用Task.Factory.StartNew(()=>{NotifyUser();})代码>。您可以添加它作为答案,这样我就可以接受它了。您还可以添加性能问题的要点(如果有)吗?没有,性能将与在同一线程中执行函数完全相同。在ASP.NET中使用Task.Run
是一个糟糕的主意。说这不会对性能产生影响也是不正确的,因为处理一个请求所需的线程基本上增加了一倍。@YuvalItzchakov为什么?你能详细说明一下吗?我在ASP.net上使用了很多工作线程,没有任何问题。线程池将处理运行的工作线程数,因此根本没有问题,也不会影响性能。线程数不会增加一倍,如果达到线程池的限制,它将对任务进行排队,直到释放任何线程。