我读到的任何地方都应该使用ConfigureAwait(false)
来避免死锁和出于性能原因。我们在我们的应用程序中使用ConfigureAwait
。但是可能会删除ConfigureAwaits,因为它会导致不同的线程的执行上下文。
不同线程的执行上下文导致(有时)翻译问题。由于当前文化和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是一个非常糟糕的主意吗?
答案 0 :(得分:10)
请勿盲目使用ConfigureAwait
表现。在编写代码(通常是库代码)时使用它,在同一线程/同步上下文中恢复无关紧要。如果在正确的线程/同步上下文上恢复很重要,ConfigureAwait(false)
将会破坏您的代码,然后它的速度无关紧要。
答案 1 :(得分:3)
您使用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上下文线程。
但是因为你总是做更多的工作,每个逻辑操作都需要更长的时间。
在客户端用户界面上,用户仍然可以使用该应用程序,或者至少不会在标题栏和任务管理器上获得“无响应”短语。
在ASP.NET上,因为有更多线程可用于处理请求,所以在负载很重的情况下,它会更快,因为允许请求立即开始工作而不是在请求队列中被阻塞。