异步和同步方法

时间:2017-09-15 12:42:05

标签: c# async-await

我有一个异步方法:

public async Task<Foo> GetFooAsync();

我需要它的同步版本。像这样:

public Foo GetFoo();

我真的不想完全重写GetFooAsync的代码,我想做一些像

这样的事情
public Foo GetFoo() 
{
    return GetFooAsync().GetAwaiter().GetResult();
}

这是好主意还是这种方法有任何不明显的问题?据我所知,如果我在同步上下文中使用GetFooAsync().Result,我可能会面临死锁。但是GetFooAsync().GetAwaiter().GetResult()呢?

3 个答案:

答案 0 :(得分:4)

混合同步/异步代码可能会导致死锁as described in this article(段落'始终异步')。

问题是Task延续的运行位置,取决于当前的SynchronizationContext。如果同步意图安排在当前通过调用Wait() / Result / GetResult()而被阻止的同一个主题上,则您遇到了麻烦

答案 1 :(得分:3)

如果您想要同步版本,则分别添加方法的异步重载以获得SOC(Separation Of Concern)。 I.c,像你已经完成的那样添加如下的重载

public Foo GetFoo() 
{
  ///code body
}

答案 2 :(得分:3)

你应该隐藏同步运行方法背后的异步实现,例如使用

Task.Run(async () => await GetFooAsync());

单独实现同步版本或让使用者显式同步GetFooAsync。 问题是,运行任务将消耗工作线程,并且可用工作池的数量有限。您可能会遇到阻止代码。因此,API消费者应该意识到同步实现是异步处理的。