Próbuję wysłać wiadomość e-mail jako powiadomienie do użytkownika i chcę, aby działała pod numerem asynchronously
. Początkowo realizowane z Task.Factory.StartNew
jak poniżej:Zadanie lub wątek nie działa/działa po uruchomieniu na serwerze
Task.Factory.StartNew(() => { _notify.NotifyUser(params); });
NotifyUser
jest void method
które faktycznie wysyła wiadomość e-mail do użytkownika.
Ale nigdy nie wykonywał tej metody. Umieściłem metodę log message
wewnątrz NotifyUser
, która nigdy nie była rejestrowana.
Śledziłem this post
i poznał, że
Czasami tego rodzaju zachowanie jest oznaką przeciążonej puli wątków. Widząc, jak są one długie bieganie/zadania blokujące, nie powinny być zaplanowane w puli wątków, czyli tam, gdzie Task.Factory.StartNew będzie wysyłał je za pomocą domyślnej TaskScheduler
a więc po co sugerowano tam, który jest jak poniżej:
ThreadStart action=()=>{
_notify.NotifyUser(params);
};
Thread thread=new Thread(action){IsBackground=true};
thread.Start();
Nie znalazłem też szczęścia w powyższym podejściu. Znowu podążyłem za jeszcze jednym podejściem, które nawet nie zadziałało.
Task task = new Task(() => {
_notify.NotifyUser(params);
});
task.RunSynchronously(); //or task.Start();
Czy istnieje jakikolwiek inny sposób na wykonanie tego zadania związanego z wysyłaniem wiadomości e-mail? Słyszałem o async await
, ale czytałem, że nie będzie on używany na void methods
. Czy ktoś może mi powiedzieć, jakie byłoby najlepsze podejście?
Aktualizacja
ThreadPool.QueueUserWorkItem(t =>
{
_notify.NotifyUser(params);
});
tak, że będzie wykonać tę metodę, gdy wątek jest dostępna. Ale wciąż nie ma tu szczęścia.
rzeczywisty kod
[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);
}
}
}
Gdzie jest kod, który pokazałeś nam w swoim projekcie? Czy jest w środku metody działania kontrolera, czy gdzieś indziej? – Fabjan
@Fabjan .. Tak .. Jest to metoda działania kontrolera. –
Po pierwsze zmień tag "C# 4.0" na * .NET Framework * 4.0, ponieważ jest to mylące. Usunąłem moją odpowiedź, ponieważ w .NET 4.0 nie można użyć 'async await' lub' Task.Run() '(oba wprowadzone w wersji 4.5). Na .NET 4.0 wydajesz się wypróbować wszystkie opcje, które mogę wymyślić. Wywołanie w 'Task.Factory.Funkcja StartNew() 'powinna wystarczyć do rozpoczęcia nowego zadania, zakładając, że istnieje kilka * dostępnych wątków * w puli wątków. – Fabjan