ASP.NET 要求使用相同的 SynchronizationContext
控制器中的异步操作,否则它会阻塞
正在运行的线程。
我不太确定那句话是什么意思。 ASP.NET 不需要“相同”的同步上下文。为了让你进入你的HttpContext,你需要SynchronizationContext。
但是是什么目的导致微软使用相同的SynchronizationContext?
我建议您阅读 It's All About SynchronizationContext 以了解有关同步上下文的更大图景。基本上,它是一种允许您在特定线程上发布延续的机制。例如,它可用于将工作编组回 UI 应用程序内的 UI 消息循环线程。
可能正在使用 ConfigureAwait(false),它会禁用相同的
同步上下文限制,可能导致例如不可预测的行为或
性能问题
相反。将工作编组回同步上下文确实有(非常少的)开销,因为需要将请求(使用抽象 SynchronizationContext.Post)发布回所需的线程和上下文。通过使用ConfigureAwait(false),您可以节省该时间,并且只需在分配的线程上继续执行。
因此,使用 ConfigureAwait(false) 真的是一个好习惯吗?
哪里有可能?
这样做的主要原因是避免死锁。当有人调用Task.Result 或Task.Wait 而不是使用await 进行异步等待时,您会遇到经典的死锁场景,同步上下文试图将延续发布回线程,但它当前被阻止,因为Result 和Wait 正在阻止呼叫。另一个原因是您获得的性能开销较小。
编辑:
微软为什么不把这个方法封装在Task类里面呢?
看起来 ConfigureAwait(false) 只有优点。是
有什么缺点吗?
让我们想象一下以下场景:您执行一个返回Task 并使用await 等待的方法,然后立即更新一些UI 元素。现在,什么对你来说更自然?您希望隐式返回到之前的相同“环境”(UI 线程),还是希望您必须明确指定要返回到相同的环境?
我认为前者对用户来说“感觉”更自然。
例子:
public Task FetchAndReturnAsync(string url)
{
var httpClient = new HttpClient();
return httpClient.GetAsync(url);
}
你这样称呼它:
var awesomeUiResult = await FetchAndReturnAsync("http://www.google.com");
textBox.Text = awesomeUiResult;
你认为应该发生什么?是在等待之后更新文本框更自然,还是因为您现在不在原始上下文中而失败?