Task.Yield、Task.Run 和 ConfigureAwait(false) 之间有什么区别?

What's the difference between Task.Yield, Task.Run, and ConfigureAwait(false)?

据我了解,方法开头的 Task.Yield 将强制调用者继续(如果它不在等待该方法)。同时 Task.RunConfigureAwait(false) both 运行 新线程池线程上的任务,如果调用者不在等待该方法,这将再次强制调用者继续。

我无法理解 Task.Yield 和 运行 新线程池线程之间的区别,因为在它 returns 到调用者之后,它会继续执行其余的的方法,本质上是一样的。

This post 表明 YieldTask.Factory.StartNew(实际上只是 Task.Run 的旧版本)可以互换使用,这似乎让我感到困惑。

Task.Yield 在当前同步上下文或当前 TaskScheduler 上继续(如果存在的话)。 Task.Run 不会那样做。它总是使用线程池。

例如 Task.Yield 将留在 UI 线程上。

避免Task.Yield。它的语义不太清楚。链接的答案是代码味道。

Task.Yield 不是 Task.Run 的替代品,它与 Task.ConfigureAwait.

无关
  • Task.Yield - 生成一个在检查完成后立即完成的可等待对象。
  • ConfigureAwait(false) - 从忽略捕获的 SynchronizationContext.
  • 的任务生成可等待对象
  • Task.Run - 在 ThreadPool 线程上执行委托。

Task.YieldConfigureAwait 的不同之处在于它本身就是一个可等待对象,而不是另一个可等待对象(即 Task)的可配置包装器。另一个区别是 Task.Yield 确实在捕获的上下文中继续。

Task.Run 与两者不同,因为它只需要一个委托并在 ThreadPool 上运行它,您可以在 ConfigureAwait(false) 或不使用它的情况下使用它。

Task.Yield 应该用于强制异步点,而不是替代 Task.Run。当在异步方法中到达 await 时,它会检查任务(或其他可等待的任务)是否已经完成,如果已完成,它会继续同步。 Task.Yield 防止这种情况发生,因此对测试很有用。

另一种用法是在 UI 方法中,您不想占用单个 UI 线程,您插入一个异步点,其余部分安排在稍后执行时间。