因此,我尝试将电子邮件作为通知发送给用户,并且希望它运行asynchronously。最初,我使用Task.Factory.StartNew实现如下:

Task.Factory.StartNew(() => { _notify.NotifyUser(params); });


NotifyUservoid method,实际上是向用户发送电子邮件。

但是它从未执行过该方法。我在log message方法中放置了一个NotifyUser,它从未被登录过。

我跟随this post并知道


有时,这种行为表示ThreadPool重载。鉴于这些任务是长时间运行/阻止的任务,因此不应将其安排为在ThreadPool中运行,这是Task.Factory.StartNew将使用默认TaskScheduler向其发送的位置


所以我遵循了下面的建议:

ThreadStart action=()=>{
    _notify.NotifyUser(params);
};
Thread thread=new Thread(action){IsBackground=true};
thread.Start();


用上述方法也找不到运气。我再次采用了另一种方法,该方法甚至没有效果。

Task task = new Task(() => {
     _notify.NotifyUser(params);
});
task.RunSynchronously(); //or task.Start();


还有其他方法可以运行此发送电子邮件的任务吗?我听说过async await,但是我读到它不会在void methods上使用。有人可以让我知道这里最好的方法吗?



更新资料

ThreadPool.QueueUserWorkItem(t =>
{
   _notify.NotifyUser(params);
});


以便在线程可用时执行此方法。但是这里仍然没有运气。

实际代码

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddEditUser(UVModel model)
{
    if (HasPermission())
    {
         string message = string.Empty;
         bool success = false;
         string returnUrl = string.Empty;
         if (ModelState.IsValid)
         {
             using (_db = new EFDB())
             {
                   //fill user model
                   _db.Entry(user).State = state;
                   _db.SaveChanges();
                   _notify = new SendNotification();
                   _notify.NotifyUser(params); //This has to be asynchronous
                   success = true;
                   returnUrl = Url.Action("Action", "Controller", null, HttpContext.Request.Url.Scheme, HttpContext.Request.Url.Host);
                   message="success";
             }
          }
          else
                message = "Server side validation failed!";
          return Json(new { result = success, message = message, redirectUrl = returnUrl }, JsonRequestBehavior.AllowGet);
    }
    else
          return Json(new { result = false, message = "You do not have permission to perform this action!", redirectUrl = "" }, JsonRequestBehavior.AllowGet);
}


SendNotification.cs

public void NotifyUser(Parameter params)
{
    using (MailMessage mail = new MailMessage())
    {
            _db = new EFDB();
            mail.To.Add(params.toAddress);
            mail.From = params.from;

            mail.Subject = params.subject;
            mail.Body = params.body;
            mail.IsBodyHtml = true;
            mail.Priority = MailPriority.High;
            SmtpClient smtp = new SmtpClient();
            smtp.Host = "some smtp host";
            smtp.Port = 25;
            smtp.UseDefaultCredentials = false;
            smtp.EnableSsl = false;
            smtp.Credentials = new NetworkCredential("uname", "pwd");
            smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
            try
            {
                smtp.Send(mail);
            }
            catch (SmtpFailedRecipientException se)
            {
                LogError.LogMessage("SmtpFailedRecipientException Exception - " + se.Message.ToString(), context);
            }
            catch (SmtpException se)
            {
                LogError.LogMessage("SmtpException - " + se.Message.ToString(), context);
            }
    }
}

最佳答案

You should never use StartNew unless you're doing dynamic task-based parallelism。我会在我的博客中详细解释为什么要讲究细节。

假设您正在ASP.NET上运行,则应使用HostingEnvironment.QueueBackgroundWorkItem。我怀疑您在委托中看到了异常,并且QBWI会将所有异常记录到事件日志中。

07-28 02:39
查看更多