Bri*_*nga 6 c# smtpclient async-await
我不明白这两个调用SendMailAsync的实现之间的区别.大多数时候第一次,我收到一个TaskCanceledException,但是第二次,一切都按预期工作.
我认为这两种消费方法是等价的,但显然我错过了一些东西.
这似乎与之相关,但与之相反:TaskCanceledException等待时
// Common SmtpEmailGateway library
public class SmtpEmailGateway : IEmailGateway
{
public Task SendEmailAsync(MailMessage mailMessage)
{
using (var smtpClient = new SmtpClient())
{
return smtpClient.SendMailAsync(mailMessage);
}
}
}
// Caller #1 code - Often throws TaskCanceledException
public async Task Caller1()
{
// setup code here
var smtpEmailGateway = new SmtpEmailGateway();
await smtpEmailGateway.SendEmailAsync(myMailMessage);
}
// Caller #2 code - No problems
public Task Caller2()
{
// setup code here
var smtpEmailGateway = new SmtpEmailGateway();
return smtpEmailGateway.SendEmailAsync(myMailMessage);
}
Run Code Online (Sandbox Code Playgroud)
编辑:事实证明,Caller2方法也导致异常,我只是没有看到它们,因为WebJobs框架被调用了.Yuval的解释清除了所有这一切并且是正确的.
两个方法调用之间的区别在于前者await在调用时异步等待使用.因此,TaskCanceledException来自内部SendEmailAsync调用的传播,这是由于您没有等待using作用域中的异步方法,这导致SmtpClient异步调用的处理和结束之间的竞争条件.在后者中,异常被封装在返回Task对象中,我不确定你是否在等待.这就是为什么在前者中,你会立即看到异常.
应该做的第一件事是SendEmailAsync在网关内部正确等待:
public class SmtpEmailGateway : IEmailGateway
{
public async Task SendEmailAsync(MailMessage mailMessage)
{
using (var smtpClient = new SmtpClient())
{
return await smtpClient.SendMailAsync(mailMessage);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用第二种方法,避免创建状态机的开销.不同的是,现在您要保证SmtpClient只有在异步操作完成后才会处置.
| 归档时间: |
|
| 查看次数: |
504 次 |
| 最近记录: |