【问题标题】:Consequences of not awaiting不等待的后果
【发布时间】:2021-11-25 11:05:59
【问题描述】:

我有一个 .net webapi,其中包含一些用于发送电子邮件的代码。

public async Task CheckOut(CheckOutData checkOutData){
     ...
     ...
     ...
     //What are the risks if I remove the await
     await SendEmail(checkOutData);
     ...
     ...
}

public async Task SendEmail(CheckOutData checkOutData)
{
  try{
  ...
  ...
  ...
  }
  catch (exception ex){
     //log Error
  }
}

我在SendEmail 代码中设置了日志记录。我的问题是,如果我删除等待,如果在 SendEmail 完成之前执行完成,是否有可能杀死线程并且不发送电子邮件?

如果我删除等待,我是否安全?我愿意接受一个异常会被吞下,它会被记录下来。

【问题讨论】:

  • 你会得到一个任务,除非你明确告诉它运行,否则它不会运行。
  • @HansPassant 很有趣,你有证据支持吗? The docs 似乎暗示所有返回的任务应该已经处于启动状态。
  • 在阅读了this document 及其子页面之后,除了被吞没的异常之外,我找不到任何缺点。但我没有足够的信心声称这是正确的答案。

标签: .net-5 webapi


【解决方案1】:

除非整个过程停止,否则将发送电子邮件。

关于线程,我们可以将 SendEmail 分为两部分:

SendEmail
   // Code that will run on the calling thread. This is the code that will prepare the data and send it to the hardware.
   // Code that will run on a thread-pool thread. This is the  code that will run after the hardware will finish sending the message.

方法的第一部分将保存原始线程,因此线程在完成之前不会被释放。第二部分将在线程池线程上运行,因此原始线程是否被释放并不重要。

编辑: 如果您在 IIS 上托管应用程序,则应用程序域可能会被回收,因此不建议运行持续请求的代码。这篇博文中有描述https://blog.stephencleary.com/2012/12/returning-early-from-aspnet-requests.html

在自托管情况下,此功能不存在 (Application pool recycling with Selfhosting a ASP.NET application)。因此,您可以使用 Task.Run 运行一个长时间运行的进程 Long running task in ApiController (using WebAPI, self-hosted OWIN)

因此,在自托管情况下,您可以避免等待。您不会等待的方法部分不会被杀死。就像上面描述的 Task.Run 案例一样。

希望对你有帮助

【讨论】:

  • 你能提供参考吗?
  • @David,编辑了回复,添加了一些参考和警告(IIS 托管案例)
猜你喜欢
  • 1970-01-01
  • 2020-02-10
  • 2017-02-03
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多