我有一个webApi设置(WebApi2)。 post方法的一个要求是(取决于一些变量)发送2封电子邮件。
我不希望客户端等待发送电子邮件。我希望他们只是提出请求并继续前进。
所以我认为我应该使用smtpClient.SendAsync,但我一直在客户端上获得http 500内部错误 - 一个c#winforms app
当我使用普通的smtpClient.Send时工作正常。但不是SendAsync。 我似乎无法抓住服务器上的错误来找到问题 - 驱使我有点稀,并且错误没有帮助。我只能假设它是由于错误地发送电子邮件
示例代码如下
//Web api code
private MessageDto _messageDto = null;
public void PostAddinObject(AddinObject newObject)
{
_messageDto = new MessageDto();
_messageDto.Email = "bob@moo.com";
..do dome otherstuff
SendMail("Hello Dot");
SendMail("Hello Peg");
..finish up and leave
}
private void SendMail(String msg)
{
using (var message = new MailMessage())
{
message.To.Add(_messageDto.Email);
message.Subject = "Hello;
message.Body = msg
try
{
Attachment datAttachment = new Attachment(_pdfFilePath, MediaTypeNames.Application.Pdf); //gets the pdf file from somewhere special
ContentDisposition disposition = datAttachment.ContentDisposition;
disposition.CreationDate = File.GetCreationTime(_pdfFilePath);
disposition.ModificationDate = File.GetLastWriteTime(_pdfFilePath);
disposition.ReadDate = File.GetLastAccessTime(_pdfFilePath);
message.Attachments.Add(datAttachment);
}
catch (Exception exception)
{
throw;
}
var smtpClient = new SmtpClient();
smtpClient.SendCompleted += new SendCompletedEventHandler(OnSendCompletedCallback);
smtpClient.SendAsync(message, null);
}
}
winforms代码:
HttpClient _client=new HttpClient();
var response = _client.PostAsJsonAsync("api/Addin", newObject).Result;
答案 0 :(得分:3)
您可以使用Task.WhenAll
到await
个多项任务。这将确保第一封电子邮件不会阻止第二封电子邮件。在下面的示例中,请求大约需要3秒钟才能完成(请注意Task.Delay
方法中的SendEmail
)。
public async Task Post()
{
await Task.WhenAll(
SendEmail("a@b.com"),
SendEmail("b@c.com")
);
}
private async Task SendEmail(string to)
{
using (var client = new SmtpClient())
{
await Task.Delay(3000);
await client.SendMailAsync(
new MailMessage("test@test.com", to, "Test", "Test"));
}
}
你说:
我希望他们只是提出请求并继续前进。
严格地说,上面的内容仍然让客户等待回复,这比你以前做的更有效。
如果您想“发射并忘记”,那么推荐的方法是将电子邮件添加到队列/数据库,并使用后台进程/服务来实际发送电子邮件。
也就是说, 可能只是在后台线程上启动工作,但是你应该谨慎行事并确保添加适当的异常处理:
public void Post()
{
Task.Factory.StartNew(() =>
{
SendEmail("a@b.com");
SendEmail("b@c.com");
});
}
这将立即返回,而不是等待发送电子邮件。这也意味着你无法真正给你的客户任何成功的迹象。
答案 1 :(得分:0)
调用SendAsync后,您必须等待电子邮件传输到 在尝试使用“发送”发送另一封电子邮件之前完成 或SendAsync。
此外,我确保在发送电子邮件之前不会销毁SmtpClient
对象。您的代码不提供该保证。