Task.Yield(); SyncAction(); vs Task.Run(()=> SyncAction());

Dev*_*345 5 c# task-parallel-library async-await

假设我想快速使以下方法异步运行:

ResultType SynchronousCode(ParamType x)
{
     return SomeLongRunningWebRequest(x);
}
Run Code Online (Sandbox Code Playgroud)

以下两个代码示例的执行/计划方式有何不同?

async Task<ResultType> AsynchronousCode(ParamType x)
{
    return await Task.Run(() => SomeLongRunningWebRequest(x));
}
Run Code Online (Sandbox Code Playgroud)

相比:

async Task<ResultType> AsynchronousCode(ParamType x)
{
    await Task.Yield();
    return SomeLongRunningWebRequest(x);
}
Run Code Online (Sandbox Code Playgroud)

我知道Task.Yield()调用将确保线程立即返回到调用者,并且Task.Run()肯定会调度代码在ThreadPool上的某个地方运行,但是这两种方法都能有效地实现该方法异步?让我们假设这个问题我们在默认的SynchronizationContext上.

Evk*_*Evk 6

虽然两个选项都很糟糕,但存在差异(在GUI应用程序中很重要):在Task.Yield返回之后,方法的其余部分将被分派回原始版本SynchronizationContext.如果你从UI线程运行它,你的长时间运行操作将在UI线程上执行,从而冻结它.因此,如果您的目的是避免UI阻止 - Task.Yield将无法正常工作.随着Task.Run这不会发生.

  • 我想在默认情况下,它没有任何区别.但我很难想象除了UI应用程序之外的任何地方都会这样做(以避免阻塞) (3认同)
  • 调用`Task.Yeild()`更糟糕,因为你知道某些事情会在后台线程上运行,而后者线程会在后台线程上运行,但前提是你以正确的方式调用它.两个选项都不好的原因是为同步函数创建异步包装[无论如何都是反模式](https://blogs.msdn.microsoft.com/pfxteam/2012/03/24/should-i-expose-asynchronous- wrappers-for-synchronous-methods /),你不应该这样做.让调用者调用`Task.Run(如果需要,调用``SynchronousCode`. (3认同)