This question already has answers here:
Calling async methods from non-async code
(4个答案)
1年前关闭。
我有一个异步任务,需要同步调用(是的,不幸的是,这是不可避免的)。似乎有两种方法可以实现此目的-每种方法似乎都有效。因此,我不确定哪种方法最好,或者是否有更好的方法。
例如:
如果有人可以解释为什么一种方法比另一种更好,那将不胜感激。谢谢! 您知道您的代码正在没有一个应用程序模型(控制台应用程序,ASP.NET Core,Windows服务)下运行 您已在当前堆栈中先前等待的不完整 您已明确调用
因此,您会发现,要考虑的事情很多,因此,通常来说,您几乎总是想使用
(4个答案)
1年前关闭。
我有一个异步任务,需要同步调用(是的,不幸的是,这是不可避免的)。似乎有两种方法可以实现此目的-每种方法似乎都有效。因此,我不确定哪种方法最好,或者是否有更好的方法。
例如:
var meetings = Task.Run(() => GetTodaysMeetingsAsync()).GetAwaiter().GetResult();
var meetings = GetTodaysMeetingsAsync().GetAwaiter().GetResult();
如果有人可以解释为什么一种方法比另一种更好,那将不胜感激。谢谢!
最佳答案
当您使用Task.Run
时,委托(delegate)的初始同步部分在线程池线程上运行,而仅().GetAwaiter().GetResult()
将在同一线程上运行该同步部分。
使用Task.Run(...).GetAwaiter().GetResult()
可以作为一种解决方法来运行异步代码并同步等待它,这不会导致异步死锁,而().GetAwaiter().GetResult()
可以。请注意,它仍然不是“安全的”,因为您可能会在服务器上的线程池线程中进行阻塞,这可能导致负载时线程池耗尽。
如果您想运行Task
返回方法,并且知道初始同步部分是微不足道的,并且您知道异步方法的其余部分将不会与SynchronizationContext
一起运行,那么().GetAwaiter().GetResult()
可以是一个微优化。仅当您确切知道自己在做什么时才这样做。
您怎么知道您没有SynchronizationContext
运行?出于以下原因之一,SynchronizationContext.Current
将为null
:
.ConfigureAwait(false)
上使用了Task
。 SynchronizationContext.SetSynchronizationContext(null)
因此,您会发现,要考虑的事情很多,因此,通常来说,您几乎总是想使用
Task.Run(...).GetAwaiter.GetResult()
。10-08 15:25