ConfigureAwait(false) 性能测试
Posted
技术标签:
【中文标题】ConfigureAwait(false) 性能测试【英文标题】:ConfigureAwait(false) performance test 【发布时间】:2017-11-08 13:29:38 【问题描述】:我读到的所有地方都应该使用ConfigureAwait(false)
来避免死锁和出于性能原因。我们在我们的应用程序中使用ConfigureAwait
。但可能会删除 ConfigureAwaits,因为它会导致不同线程的执行上下文。
不同线程的执行上下文导致(有时)翻译问题。由于 currentculture 和 currentUICulture 中的设置文化在不同的执行上下文中无法访问。
我已经用下面的代码对其进行了一些测试。它没有任何性能差异。我知道这不是一个好的测试,因为这个简单的测试使用的线程并不多。
static async Task MyMethodAsync()
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000; i++)
await Task.Delay(10);
await Task.Delay(10).ConfigureAwait(continueOnCapturedContext: false);
stopwatch.Stop();
Console.WriteLine("Await: " + stopwatch.Elapsed.ToString());
static async Task MyMethodAsyncNoAwait()
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000; i++)
await Task.Delay(10);
await Task.Delay(10);
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed.ToString());
我应该如何正确测试这个?删除所有 ConfigureAwaits 真的是个坏主意吗?
【问题讨论】:
您不应该需要ConfigureAwait(false)
来防止死锁——这些死锁只会在您阻塞异步代码时首先发生,而您不应该这样做。
如果您使用控制台应用程序之类的东西进行测试 - 无论如何它不会有任何区别,因为没有上下文。
我会忽略性能差异。如果您在 .NET 4.6 上看到不同的 CurrentCulture
/ CurrentUICulture
值,那么这是一个错误,应该这样报告。
【参考方案1】:
不要为了性能而盲目使用ConfigureAwait
。在编写代码(通常是库代码)时使用它,在同一线程/同步上下文中恢复无关紧要。如果在正确的线程/同步上下文中恢复确实很重要,ConfigureAwait(false)
会破坏你的代码,然后它可能有多快都没关系。
【讨论】:
【参考方案2】:您对async-await
所做的一切与性能无关,而是与响应能力和可用性有关。
在 WinForms、WPF 或 UWP 等客户端 UI 上,它与响应能力有关。您在 IO 和 CPU 绑定操作上使用 async-await
在 UI 线程之外执行工作,并使用 ConfigureAwait(false)
明确避免返回到该 UI 线程。
在 ASP.NET(.NET Framework,而不是 .NET Core)上,它与可用性有关。您在 IO 操作上使用 async-await
以释放线程以处理其他请求,并使用 ConfigureAwait(false)
避免将返回线程设置为 HTTP 上下文线程。
但是因为你总是做更多的工作,每个逻辑操作都会花费更长的时间。
在客户端 UI 上,用户仍然可以使用应用程序,或者至少不会在标题栏和任务管理器上看到“没有响应”的短语。
在 ASP.NET 上,由于有更多线程可用于处理请求,因此在负载较重时,它会更快,因为允许请求立即开始工作,而不是在请求队列中被阻塞。
【讨论】:
以上是关于ConfigureAwait(false) 性能测试的主要内容,如果未能解决你的问题,请参考以下文章
为整个项目/dll 设置 ConfigureAwait(false)
ConfigureAwait(false) 与将同步上下文设置为 null
您可以在没有线程安全的情况下使用 ConfigureAwait(false) 吗?
ConfigureAwait(false) 不会使延续代码在另一个线程中运行