c# - SendMailAsync 导致 TaskCanceledException 的原因?

标签 c# async-await smtpclient

我不明白调用 SendMailAsync 的这两种实现之间的区别。大多数情况下,对于第一个,我会收到 TaskCanceledException,但对于第二个,一切都按预期进行。

我认为这两种消费方法是等价的,但显然我遗漏了一些东西。

这似乎与:TaskCanceledException when not awaiting 有关,但相反。

// 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);
}

编辑:原来 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);
        }
    }
}

然后,您可以使用第二种方法来避免创建状态机的开销。不同之处在于,现在您要保证 SmtpClient 只会在异步操作完成后进行处理。

关于c# - SendMailAsync 导致 TaskCanceledException 的原因?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33523922/

相关文章:

c# - 如何在不发送电子邮件的情况下检查 smtp 服务器?

c# - Microsoft.Threading.Tasks 引用了不正确的 System.Threading.Tasks.dll 版本

c# - 如何使 EF Core 工具从控制台应用程序的服务提供者处获取 DbContext 实例?

javascript - Promise.all() 中的第一个 promise 没有正确执行

c# - Metro C# 中的虚拟异步方法

powershell - 使用附件时,Send-MailMessage 每 2 个连接关闭一次

c# - 将列表框中的值添加到数据库

c# - 在运行时执行隐式转换

c# - 异步编程控制流程

asp.net-mvc-3 - SmtpClient.SendAsync 阻塞了我的 ASP.NET MVC 请求