在顶层一直向下同步VS异步

Ris*_*ari 0 .net c# asynchronous async-await c#-5.0

以下哪一项是使用异步等待的最佳方法.

选项1:异步等待所有功能

public async Task A()
{
   await B();
   //some code
}

public async Task<bool> B()
{
   var result= await C(); 
   //some code
   return result; 
}

public Task<bool> C()
{ 
   // not implemnted
}
Run Code Online (Sandbox Code Playgroud)

要么

选项2:异步等待仅在顶级功能中

 public async Task A()
    {
       await B();
       //some code
    }

    public async Task<bool> B()
    {
        var result= C().Result; 
        //some code
        return result; 

    }

    public Task<bool> C()
    { 
       // not implemnted
    }
Run Code Online (Sandbox Code Playgroud)

Sco*_*ain 5

选项1是正确的方法,2不应该这样做.如果您在callstack中的任何位置使用async,则不应该在代码中调用.Result.Wait()执行任务.如果你这样做,很可能你最终会使你的程序陷入僵局.

更新:旁注,如果函数B中的代码不依赖于启动函数的同一个线程(没有UI工作),那么"最好"的方法就是

public async Task A()
{
   await B();
   //some code that interacts with the UI
}

public async Task<bool> B()
{
   var result= await C().ConfigureAwait(false); 
   //some code does does not interact with the UI
   return result; 
}

public Task<bool> C()
{ 
   // not implemnted
}
Run Code Online (Sandbox Code Playgroud)

这使得系统可以使用任何可用的线程池线程,而不是在运行延续时等待同步上下文变为可用.

  • 是的,由于 async/await 的状态机,存在开销,但是如果您不这样做,如果您处于同步上下文中,您可能会死锁您的代码。在带有 UI thead 的程序中运行选项 2 示例,只需将 `await Task.Yield()` 添加到 C 以使其将控制权交还给调用者。您将在 `await B();` 行出现死锁。 (2认同)
  • 我不确定你的意思,但我认为答案可能是肯定的?我想说的是,如果在调用链的上方或下方有任何异步代码,则不应同步阻止任务. (2认同)