Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 执行后端电子邮件进程,而不让用户等待它完成_C#_Asp.net Mvc_Asp.net Mvc 4_C# 4.0_Async Await - Fatal编程技术网

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上使用了很多工作线程,没有任何问题。线程池将处理运行的工作线程数,因此根本没有问题,也不会影响性能。线程数不会增加一倍,如果达到线程池的限制,它将对任务进行排队,直到释放任何线程。