何时使用 Task.Run().GetAwaiter().GetResult() 和 ().GetAwaiter.GetResult()?

Ada*_*dam 6 .net c# asynchronous task .net-core

我有一个需要同步调用的异步任务(是的,不幸的是,这是不可避免的)。似乎有两种方法可以实现这一点——每种方法似乎都有效。所以我不确定哪种方法是最好的,或者是否有更好的方法。

例如:

var meetings = Task.Run(() => GetTodaysMeetingsAsync()).GetAwaiter().GetResult();

var meetings = GetTodaysMeetingsAsync().GetAwaiter().GetResult();
Run Code Online (Sandbox Code Playgroud)

如果有人能解释为什么一种方法比另一种方法更好,那将不胜感激。谢谢!

Stu*_*art 11

当您使用 时Task.Run,委托的初始同步部分在线程池线程上运行,而只会().GetAwaiter().GetResult()在同一线程上运行该同步部分。

UsingTask.Run(...).GetAwaiter().GetResult()可以用作运行异步代码并同步等待它的解决方法,它不会导致异步死锁,而().GetAwaiter().GetResult()可以。请注意,它仍然不是“安全的”,因为您可能在线程池线程中阻塞,在服务器上这可能导致线程池在负载时耗尽。

如果你想运行一个Task返回方法,并且知道最初的同步部分是微不足道的,并且你知道异步方法的其余部分不会用 a 运行SynchronizationContext,只是().GetAwaiter().GetResult()可以是一个微优化,我会说只做如果你确切地知道你在做什么。

你怎么知道你在 no 下运行SynchronizationContextSynchronizationContext.Current将是null,由于以下原因之一:

  • 知道您的代码在没有应用程序模型(控制台应用程序、ASP.NET Core、Windows 服务)下运行
  • 您已在当前堆栈中先前.ConfigureAwait(false)等待的不完整Task上使用过。
  • 您已明确调用 SynchronizationContext.SetSynchronizationContext(null)

所以你看,需要考虑很多,所以通常你几乎总是想使用Task.Run(...).GetAwaiter.GetResult().