问题不在于ConfigureAwait的功能。而是为什么为什么到处我都会看到类似的东西
通常,是的。除非该方法需要其上下文,否则应将ConfigureAwait(false)用于每次等待。
即他们提议我应该写
await Method1().ConfigureAwait(false);
await Method2().ConfigureAwait(false);
// Do something else
// ...
await Method3().ConfigureAwait(false);
await Method4().ConfigureAwait(false);
但是在这种情况下,只是像这样一开始就重置上下文就不太清楚了
await Task.Yield().ConfigureAwait(false);
它保证下面的代码将在没有同步上下文的情况下执行,不是吗?
即,我读到,如果该方法立即返回,则一次编写ConfigureAwait可能不起作用。对我来说,显而易见的解决方案看起来像对肯定不会立即返回的东西调用ConfigureAwait(false),哪个Task.Yield是,对吧?
我也知道Task.Yield不再包含ConfigureAwait(不知道为什么,因为我以前知道它曾经拥有过),但是查看Task.Yield代码,编写自己的方法非常容易除了用空的同步上下文调用延续之外,将无能为力。
对我来说,阅读似乎更容易,尤其是一次写时
await TaskUtility.ResetSyncContext();
而不是在每一行上写ConfigureAwait。
会工作(Task.Yield()。ConfigureAwait(false)或类似的自定义方法)还是我错过了什么?
通常,是的。除非该方法需要其上下文,否则应将ConfigureAwait(false)用于每次等待。
我经常在Stack Overflow上看到这些建议,甚至是Stephen Cleary(Microsoft MVP)在Async and Await文章中说的:
一个好的经验法则是使用ConfigureAwait(false),除非您知道确实需要上下文。
Stephen绝对知道他的知识,并且我同意该建议在技术上是准确的,但是我一直认为这是一个糟糕的建议,原因有两个:
首先,这对初学者是个坏建议,因为同步上下文是一个复杂的主题。如果您开始学习async
/await
被告知“除非该方法需要其上下文,否则ConfigureAwait(false)
应用于所有await
情况”,但您甚至不知道“上下文”是什么以及“需要”的含义,那么您就不需要知道什么时候不应该使用它,所以最终总是使用它。这意味着,除非您碰巧得知,否则您将遇到很难发现的错误,是的,您实际上确实需要“上下文”内容,而这种神奇的“ ConfigureAwait”内容使您迷失了它。您可能会花费数小时试图找出答案。
对于任何类型的应用程序,我相信建议确实应该相反:完全不要使用ConfigureAwait
,除非您知道它的用途,并且确定在此行之后绝对不需要上下文。
但是,根据之后调用的方法,确定您是否不需要上下文可以很简单,也可以很复杂。但即便如此-这是第二个原因我那个建议不同意-只是因为你并不需要这一行后的背景下,现在,这并不意味着一些代码不会在以后添加,将使用的上下文。您必须希望进行更改的人知道做什么ConfigureAwait(false)
,看到并删除。ConfigureAwait(false)
在任何地方使用都会产生维护风险。
这是另一位Stephen,Stephen Toub(Microsoft雇员)在“何时应使用ConfigureAwait(false)?”标题下的ConfigureAwait FAQ中建议的:
编写应用程序时,通常需要默认行为(这就是为什么它是默认行为)。...这导致以下一般指导:如果您正在编写应用程序级代码,请不要使用
ConfigureAwait(false)
在我自己的应用程序代码中,我不必费心尝试找出可以使用和不能使用它的地方。我只是忽略了那个ConfigureAwait
存在。当然,可以通过使用它来提高性能,但是我真的怀疑这对任何人来说都不会有明显的区别,即使可以通过计时器来衡量。我不认为投资回报率是正的。
唯一的例外是在编写库时,正如Stephen Toub在他的文章中指出的那样:
如果您正在编写通用库代码,请使用
ConfigureAwait(false)
这有两个原因:
要解决您的问题中的另一点:ConfigureAwait(false)
在第一个await
而不是其余的上使用并不总是足够的。在您的库代码中的每一个 上使用它await
。Stephen Toub在标题“在我的方法中仅在第一次等待而不在其余等待中使用ConfigureAwait(false)可以吗?”的文章。说,部分:
如果
await task.ConfigureAwait(false)
涉及到在等待时已经完成的任务(这实际上是非常普遍的),则这ConfigureAwait(false)
将是没有意义的,因为线程在此之后继续在该方法中执行代码,并且仍在与之前相同的上下文中执行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句