【问题标题】:Does await keyword wait indefinitely or does it have a limit?await 关键字是无限期等待还是有限制?
【发布时间】:2022-11-24 00:57:10
【问题描述】:

如果您使用 await 关键字,它是否有任何限制或是否会无限期地等待任务完成?

编辑:我的完整背景是......

前端应用程序向异步 Web API 端点发出非异步 HTTP 请求。最终,端点将等待对数据库上存储过程的调用。前端应用程序在大约 100 秒后遇到 HTTP 超时。如果过程需要 35 分钟才能完成,

  1. await 方法是否会等待 35 分钟让过程完成或是否有限制?
  2. 当 HTTP 超时在 100 秒后完成时,等待调用会发生什么情况?
  3. 如果继续运行,当 proc 在 35 分钟后返回响应时会发生什么?

【问题讨论】:

  • 我觉得这个问题还有更多内容。你想做什么?
  • Task 每个定义只是一项工作。它对时间限制或其他任何事情一无所知,只知道它已经开始并且最终会终止。
  • “等待线程是否会等待……”-- 有no await thread。您可能指的是异步方法的执行流程。
  • await 将无限期等待,但一段时间后取消 await 并不能保证实际操作会停止。鉴于网络调用无论如何都是异步的,request to an async Web API endpoint. 是什么意思?您可能不仅需要取消等待,还需要通知 API 取消其操作

标签: c# async-await


【解决方案1】:

await 关键字无限期等待。等待是没有限制的。例如下面的 await 将永远不会继续执行下一行代码。执行流程将永远卡在await

await Task.Delay(Timeout.Infinite);
throw new UnreachableException(); // This line is unreachable.

从 .NET 6 开始,TaskTask<T>ValueTaskValueTask<T> 类型有一个 WaitAsync 方法,它返回一个在指定时间段后完成的新任务(由 TimeSpan 表示) ).如果 timeout 在基本任务完成之前过去,则 WaitAsync 任务传播 TimeoutException

【讨论】:

  • 谢谢你的解释。所以第一个问题的答案是,它会无限期地等待。在等待任务完成之前,发起 HTTP 请求超时是否会影响等待?如果不是,当任务在 35 分钟后完成时会发生什么?
【解决方案2】:

await 将无限期等待,除非操作本身取消。虽然您可以使用不会停止异步操作本身的 CancellationTokenSource 或 Task.WaitAsync 取消它。

在问题的情况下:

  1. await 会继续等待,但
  2. HTTP请求会超时,所以await会以超时异常结束
  3. 端点不会注意到任何事情,存储过程将继续运行 35 分钟。
  4. 任何结果都将丢失,因为客户端不再等待它们

    如果您想实际取消存储过程,则必须修改端点以处理取消请求并以某种方式取消存储过程

    一种方法是向执行存储过程的工作代码发出取消信号。取消 ExecuteNonQuery 调用不会取消存储过程本身,但如果代码使用显式数据库事务运行,则取消异常将中止事务和存储过程。

    另一种选择是终止执行存储过程的数据库会话。这将需要一些簿记,以在调用 ExecuteNonQuery 之前存储正在执行的连接的会话 ID。

    Stephen Toub 在How do I cancel non-cancelable async operations? 中描述了这些含义。结论是

    那么,你能取消不可取消的操作吗?不可以。您可以取消对不可取消操作的等待吗?当然……只是当你这样做的时候要非常小心。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 2021-03-09
    • 2012-05-12
    • 2011-10-23
    • 2013-06-03
    • 1970-01-01
    相关资源
    最近更新 更多