首页 文章

关于MVC中异步/等待的矛盾建议

提问于
浏览
1

我一直在开发一些将由MVC动作方法使用的库代码,所以我一直在阅读很多Steven Cleary关于这个主题的博客 .

我跑进他的“Don't Block on Async Code”博客文章,但我对一些似乎相互矛盾的部分感到困惑 .

在“防止僵局”下,他说:

有两种最佳实践(我的介绍文章中都包含这些内容)可以避免这种情况:在“库”异步方法中,尽可能使用ConfigureAwait(false) . 不要阻止任务;一直使用async .

然后呢:

使用ConfigureAwait(false)来避免死锁是一种危险的做法 . 您必须对阻塞代码调用的所有方法的传递闭包中的每个等待使用ConfigureAwait(false),包括所有第三方和第二方代码 . 使用ConfigureAwait(false)来避免死锁充其量只是一个黑客攻击 .

鉴于这两个语句,有人说 ConfigureAwait(false) 是库代码的最佳实践,并且说它最多是一个危险的黑客,编写在MVC中使用时不会死锁的库代码的实际正确方法是什么?

我已经阅读了关于SO的其他问题和答案,可能被认为是重复的,但它们似乎都没有解决一位专家在async / await上给出的矛盾信息 .

1 回答

  • 3

    除非你将它们脱离背景,否则这些信息不会直接相互矛盾:

    前者是编写库代码的一般建议;做这些事情是个好主意,以确保你的库表现良好,无论它调用的同步上下文如何 .

    后者明确地提到如何使用 ConfigureAwait(false) 作为避免 known 死锁场景的手段 . 它说,

    我想阻止这里,但这样做通常会导致死锁,所以我会将工作推送到另一个线程(来自线程池)并希望一切正常 .

    如果遵循先前的建议不阻止任务(一直使用异步),那么这种死锁情况就不会发生 .

    死锁场景仅在特定同步上下文中运行代码时才有意义,该特定同步上下文在启动任务的线程上安排继续执行,例如ASP.NET使用的(在一个线程上处理请求)或Windows使用的那个桌面应用程序(所有UI事件的单个线程) .

    在这些上下文中阻塞任务会导致单个线程被阻塞,因此线程永远不会自由运行continuation和方法死锁 .

相关问题