为什么我需要在所有的传递闭包中使用ConfigureAwait(false)?

10 浏览
0 Comments

为什么我需要在所有的传递闭包中使用ConfigureAwait(false)?

我正在学习async/await,并在阅读了这篇文章Don't Block on Async Code

以及这篇文章Is async/await suitable for methods that are both IO and CPU bound之后,我注意到了@Stephen Cleary的一条提示。

使用ConfigureAwait(false)来避免死锁是一种危险的做法。你必须在所有被阻塞代码调用的方法的传递闭包中使用ConfigureAwait(false),包括所有的第三方和第二方代码。使用ConfigureAwait(false)来避免死锁充其量只是一个hack)。

在上面附上的代码中,它再次出现了。

public async Task LoadPage(Uri address)
{
    using (var httpResponse = await new HttpClient().GetAsync(address)
        .ConfigureAwait(continueOnCapturedContext: false)) //IO-bound
    using (var responseContent = httpResponse.Content)
    using (var contentStream = await responseContent.ReadAsStreamAsync()
        .ConfigureAwait(continueOnCapturedContext: false)) //IO-bound
    return LoadHtmlDocument(contentStream); //CPU-bound
}

根据我的了解,当我们使用ConfigureAwait(false)时,其余的async方法将在线程池中运行。为什么我们需要在传递闭包中的每个await中添加它呢?我个人认为这是正确的版本,就像我所知道的那样。

public async Task LoadPage(Uri address)
{
    using (var httpResponse = await new HttpClient().GetAsync(address)
        .ConfigureAwait(continueOnCapturedContext: false)) //IO-bound
    using (var responseContent = httpResponse.Content)
    using (var contentStream = await responseContent.ReadAsStreamAsync()) //IO-bound
    return LoadHtmlDocument(contentStream); //CPU-bound
}

这意味着在using块中的第二次使用ConfigureAwait(false)是无用的。请告诉我正确的方法。

提前感谢。

0