我有以下的控制方法發送郵件異步獲取視圖結果後執行返回
public async Task<ActionResult> SendToAllUsers(SentMailToAllUsersModel model)
{
if (ModelState.IsValid)
{
var mail = MailService.SendMailToAllUsers(model.Body, model.Title);
await mail;
}
return View(model);
}
這是調用此方法上的郵件服務
public Task SendMailToAllUsers(string content, string title)
{
var users = UserService.GetAllUsers();
var mailTemplates = users.Result.AsParallel().Select(user =>
{
var mailTemplate = new MastersMailTemplate(user);
mailTemplate.HtmlEmailTemplate = content;
mailTemplate.Subject = title;
mailTemplate.From = _fromEmail;
return Task.Factory.StartNew(() => MailProvider.SendEmailAsync(mailTemplate.CreateMailMessage(), new ResultDescription()).ConfigureAwait(false));
}).ToArray();
return Task.WhenAll(mailTemplates);
}
此方法觸發郵件提供商執行此方法:
public Task<IResultDescription> SendEmailAsync(MailMessage message, IResultDescription rd)
{
// Create our SMTP Client
SmtpClient client = new SmtpClient();
client.Host = SmtpServer;
client.Port = SmtpServerPort;
client.Credentials = new NetworkCredential(SmtpServerUsername, SmtpServerPassword);
client.EnableSsl = true;
if (AppSettings.IsInTestMode)
{
Log.Info("Test mode check: Removing all emails and replace to test");
message.To.Clear();
foreach (var email in AppSettings.DefaultTestEmail)
{
message.To.Add(new MailAddress(email));
}
}
client.Timeout = 10;
Log.Info("Sending Email to" + message.To.FirstOrDefault());
var task = Task.Run(async() =>
{
try{
client.SendCompleted += (s, e) =>
{
client.Dispose();
message.Dispose();
};
await client.SendAsync(message);
rd.Success = true;
return rd;
}
catch (Exception e)
{
Log.Error("Email not send");
rd.Success = false;
if (rd.Errors == null)
{
IList<string> errors = new List<string>();
errors.Add(e.Message);
rd.Errors = errors;
}
else
{
rd.Errors.Add(e.Message);
}
return rd;
}
});
return task;
}
問題是結果視圖返回在任何發送郵件之前清除。
控制器不會等待直到發送所有郵件。
如何確保控制器僅在郵件服務中的所有任務完成時才繼續執行?
爲什麼你要做'await client.SendAsync(...)',如果你只是做'client.Send(...)'? – elgonzo
謝謝elgonzo,這個工作! – Identity
請注意,* SendCompleted *事件未針對'client.Send(...)'觸發。然而,這不是一個真正的問題,因爲你可以把你的* SendCompleted *處理程序的代碼放在'client.Send(...)'後面(注意,每當發生異常時,那些.Dispose()調用不是正在製作) – elgonzo