Così sto cercando di inviare e-mail come notifica all'utente e voglio che venga eseguito asynchronously
. Inizialmente ho implementato con Task.Factory.StartNew
come di seguito:Attività o Thread non funzionanti/in esecuzione quando sono ospitati sul server
Task.Factory.StartNew(() => { _notify.NotifyUser(params); });
NotifyUser
è un void method
che in realtà invia e-mail all'utente.
Ma non è mai stato in esecuzione il metodo. Ho inserito un log message
all'interno del metodo NotifyUser
, che non è mai stato registrato.
ho seguito this post
ed è venuto a sapere che
A volte questo tipo di comportamento è indice di un ThreadPool sovraccarico. Visto che questi sono lunghi da corsa/compiti di blocco, non dovrebbero essere programmati per l'esecuzione in ThreadPool, che è dove Task.Factory.StartNew sarà l'invio utilizzando il default TaskScheduler
e così ho seguito quello che è stato suggerito c'è qui sotto:
ThreadStart action=()=>{
_notify.NotifyUser(params);
};
Thread thread=new Thread(action){IsBackground=true};
thread.Start();
Non ho trovato fortuna con l'approccio di cui sopra. Di nuovo ho seguito un altro approccio che non ha funzionato.
Task task = new Task(() => {
_notify.NotifyUser(params);
});
task.RunSynchronously(); //or task.Start();
Esiste un altro modo per eseguire questa attività di invio di posta elettronica? Ho sentito parlare di async await
ma ho letto che non verrà utilizzato su void methods
. Qualcuno può farmi sapere quale sarebbe l'approccio migliore qui?
Aggiorna
ThreadPool.QueueUserWorkItem(t =>
{
_notify.NotifyUser(params);
});
modo che possa eseguire questo metodo quando il filo è disponibile. Ma ancora senza fortuna qui.
codice vero e proprio
[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);
}
}
}
Dove è il codice che ci hai mostrato nel tuo progetto? È all'interno del metodo di azione del controller o da qualche altra parte? – Fabjan
@Fabjan .. Sì .. È nel metodo di azione del controllore. –
Prima di tutto cambia il tag 'C# 4.0' in * .NET Framework * 4.0 perché è confuso. Ho rimosso la mia risposta perché in .NET 4.0 non è possibile usare 'async await' o' Task.Run() '(entrambi introdotti nella versione 4.5) Su .NET 4.0 sembra che tu abbia provato tutte le opzioni a cui posso pensare. La chiamata su Task.Factory.StartNew() 'dovrebbe essere sufficiente per avviare una nuova attività presumendo che ci siano alcuni * thread disponibili * in un pool di thread. – Fabjan