我有一个异步方法:
public async Task<Foo> GetFooAsync();
我需要它的同步版本。像这样:
public Foo GetFoo();
我真的不想完全重写GetFooAsync
的代码,我想做一些像
public Foo GetFoo()
{
return GetFooAsync().GetAwaiter().GetResult();
}
这是好主意还是这种方法有任何不明显的问题?据我所知,如果我在同步上下文中使用GetFooAsync().Result
,我可能会面临死锁。但是GetFooAsync().GetAwaiter().GetResult()
呢?
答案 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消费者应该意识到同步实现是异步处理的。