【问题标题】:async all the way down VS async on top level [closed]一直异步VS顶层异步[关闭]
【发布时间】:2018-02-10 18:39:30
【问题描述】:

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

选项 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
}

选项 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
    }

【问题讨论】:

    标签: c# .net asynchronous async-await c#-5.0


    【解决方案1】:

    选项 1 是正确的做法,不应该做 2。如果您在调用堆栈中的任何位置使用异步,则永远不应在代码中的任务上调用.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
    }
    

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

    【讨论】:

    • 编辑了我的问题...在函数 B 中我必须根据结果进行一些处理
    • 函数 B 中的代码是否以任何方式依赖于 UI?如果没有,我更新了我的答案以显示更好的方法。
    • 不.. 不需要 UI 上下文
    • 是的,由于 async/await 的状态机存在开销,但如果你不这样做,如果你在同步上下文中,你可能会死锁你的代码。在带有 UI 主题的程序中运行您的选项 2 示例,只需将 await Task.Yield() 添加到 C 以使其将控制权交还给调用者。您将在await B(); 行出现死锁。
    • 我不确定你的意思,但我认为答案可能是肯定的?我想说的是,如果在调用链中您上方或下方的任何位置都涉及异步代码,则您永远不应该同步阻塞任务。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 2023-01-20
    • 2020-12-02
    • 1970-01-01
    • 1970-01-01
    • 2019-03-11
    • 2013-09-19
    相关资源
    最近更新 更多