gpt4 book ai didi

c# - SendMailAsync 导致 TaskCanceledException 的原因?

转载 作者:太空狗 更新时间:2023-10-29 21:32:57 26 4
gpt4 key购买 nike

我不明白调用 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com