【问题标题】:Is calling Task.Yield in Asp.Net Core ensuring continuation to run on the ThreadPool?在 Asp.Net Core 中调用 Task.Yield 是否确保继续在 ThreadPool 上运行?
【发布时间】:2021-08-22 03:03:36
【问题描述】:

所以Task.Yield 将立即将执行返回给调用者,实质上是在它返回的任务的延续中继续执行它 (Task.Yield)。

假设一个没有SynchronizationContext 的 Asp.Net Core 应用程序与等待Task.Yield 并将该延续传递给Task.Run 有任何功能区别吗?

【问题讨论】:

  • 我假设您的问题具有教育目的。出于实际目的,如果您的意图是强制切换到 ThreadPool,则像 noseratio 的 SwitchTo 这样的专用机制将清楚地传达此意图,并稳健地执行此行为,而不是依赖可能产生的 Task.Yield 之类的机制这种行为是偶然的,具体取决于应用程序的环境状态。
  • @TheodorZoulias 是的,你的假设是正确的。
  • 代码已经在线程池线程中运行。为什么要强制上下文切换和使用更多线程?
  • @PauloMorgado 你能详细说明你说的话吗?这对我来说没有意义。什么代码已经在线程池线程中运行?

标签: c# asp.net-core async-await


【解决方案1】:

假设一个没有 SynchronizationContext 的 Asp.Net Core 应用程序,与等待 Task.Yield 并将该延续传递给 Task.Run 是否有任何功能差异?

几乎没有区别。 await Task.Yield 将继续排队到线程池并返回给调用者。 await Task.Run 会将其委托排队到线程池并返回给调用者。

就我个人而言,我更喜欢Task.Run,因为它有一个非常明确的意图并且是明确的(即,在其他情况下,例如 GUI 线程,await Task.Yield 不会排队到线程池,而await Task.Run 总是这样做无论上下文如何,都是一样的)。

正如其他人在 cmets 中指出的那样,没有理由在 ASP.NET Core 上实际执行任何一个,因为它已经在线程池线程上运行并且没有请求上下文。这会给请求增加一点开销,而根本没有任何好处。

【讨论】:

  • 实际上,当我问这个问题时,我想到了BackgroundService(你在另一个问题中也回答了我这个问题:P)。 BackgroundService.ExecuteAsync 实际上会在应用程序启动线程返回给调用者之前阻止它,例如等待Task.Yield。如果我正确理解了您所说的内容,那么在BackgroundService.ExecuteAsync 的情况下应该首选Task.Run,因为它所表达的内容。虽然Task.Yield 会做同样的事情(如你所说),但它表达的意图不如Task.Run,因此应该使用后者。
  • 对于那些对我提到的另一个主题感兴趣的人:stackoverflow.com/questions/68825893/…
  • @underthevoid:啊。是的,I recommend using Task.Run in that scenario
【解决方案2】:

如果您将结果作为教育观点,它们是不同的。可以在herehere 找到更好的解释,并且...如果您想了解它如何编译为 IL,请尝试here

从现实世界的项目中,我看到Task.Yield 的唯一目的和好处是强制任务异步运行。 (将方法装饰为async/await 并不能确保它们会异步运行,尤其是使用新的ValueTask)。

因此,强制立即将执行返回给调用者,意味着您不关心它的最终结果(例如:您调用 API,但从不关心响应)。

根据我的说法,在 asp.net 核心服务器端进程中,有一个更好的方法,那就是构建一个 FireAndForget 服务并将任务传递给它,让它们在单独的范围内运行会更安全。

这是因为Task.Yield 将捕获当前上下文并继续它。因此,如果您使用与当前执行范围相关的资源,很可能会发生异常,HttpRequest 是一种特殊情况,通常会在不到一秒的时间内完成(HttpContext 已经被释放)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多