C#异步等待.NetCore中出现的死锁问题?

Lil*_*m4n 7 c# asynchronous async-await asp.net-core

在.NetFramework中,使用以下方法同步到同步上下文时发生死锁的风险很高:

var result =  asyncMethod().Result; 
var result =  asyncMethod().GetAwaiter().GetResult();
Run Code Online (Sandbox Code Playgroud)

代替

var result = await asyncMethod();
Run Code Online (Sandbox Code Playgroud)

(阅读Stephen Cleary博客文章了解更多信息)

由于.NetCore中已删除同步上下文.这是否意味着上述方法现在可以安全使用?

Chr*_*att 6

是和否。.NET Core 中确实没有同步上下文,因此,死锁问题的主要来源之一已被消除。然而,这并不意味着死锁是完全不可能的。无论如何,您不应该让良好的编程实践滑倒,仅仅因为它在某种情况下可能不再是一个大问题。尤其是 ASP.NET Core,它是完全异步的,因此没有理由使用同步版本的方法或简单地阻塞异步任务。await像往常一样使用。

  • @Lillem4n 好吧,Stephen Cleary [说不](https://blog.stephencleary.com/2017/03/aspnetcore-synchronization-context.html)。 (2认同)
  • @Lillem4n 虽然您基本上可以避免死锁,但您仍然会遇到线程池饥饿 http://labs.criteo.com/2018/10/net-threadpool-starvation-and-how-queuing-makes-it-worse/ (2认同)

Lil*_*m4n 3

您可以阻止异步代码 - 但您不应该\xe2\x80\x99t

\n\n

第一个也是最明显的结果是,await 没有捕获任何上下文。这意味着阻塞异步代码不会导致死锁。您可以使用 Task.GetAwaiter().GetResult()(或 Task.Wait 或 Task.Result)而不必担心死锁。\n但是,您应该\xe2\x80\x99t。因为当您阻止异步代码时,您\xe2\x80\x99首先就放弃了异步代码的所有好处。一旦阻塞线程,异步处理程序的增强的可伸缩性就会失效。\n不幸的是,在(旧版)ASP.NET 中有几个场景需要阻塞:ASP.NET MVC 筛选器和子操作。然而,在 ASP.NET Core 中,整个管道是完全异步的;过滤器和视图组件都是异步执行的。\n总之,理想情况下您应该努力始终使用异步;但如果您的代码需要,它可以毫无危险地阻塞。

\n\n

-摘自 Stephen Cleary 的博文

\n\n

归功于GSerg找到了这个帖子

\n\n

但是,您可能会遇到线程池饥饿的情况

\n\n

http://labs.criteo.com/2018/10/net-threadpool-starvation-and-how-queuing-makes-it-worse/

\n