什么是使用ConfigureAwait(假)和Task.Run之间的区别是什么?(What are

2019-07-20 00:29发布

据我所知,我们建议使用ConfigureAwait(false)await库码S,以便后续代码不会在调用者的执行上下文,这可能是一个UI线程上运行。 我也明白, await Task.Run(CpuBoundWork)应改为使用的CpuBoundWork()出于同样的原因。

例如用ConfigureAwait

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

例如用Task.Run

public async Task<HtmlDocument> LoadPage(Uri address)
{
    using (var client = new HttpClient())
    using (var httpResponse = await client.GetAsync(address))
        return await Task.Run(async () =>
        {
            using (var responseContent = httpResponse.Content)
            using (var contentStream = await responseContent.ReadAsStreamAsync())
                return LoadHtmlDocument(contentStream); //CPU-bound
        });
}

什么是这两种方法之间的差异?

Answer 1:

当你说Task.Run ,你是说你有一些CPU的工作要做,可能需要很长的时间,所以它应该始终在线程池中的线程中运行。

当你说ConfigureAwait(false) ,你是说那其余async方法不需要原始上下文。 ConfigureAwait是更优化的暗示; 它并不总是意味着延续上一个线程池线程上运行。



Answer 2:

在这种情况下,您的Task.Run版本将有更多的开销,作为第一个调用的await( await client.GetAsync(address) )将仍然编组回调用上下文,也将在结果Task.Run电话。

在第一示例中,在另一方面,你的第一Async()方法被配置为不需要编组回调用上下文,这允许继续到仍然在后台线程中运行。 因此,不会有任何编组回调用者的上下文。



Answer 3:

同意@Stephen答案,如果仍然混乱见下面的截图1#无ConfigureAwait(假)
请查看图片主线程下面尝试更新标签

2#随着ConfigureAwait(假)
见图像加工螺纹下方尝试更新标签



Answer 4:

作为一个方面说明,在这两种情况下LoadPage() 仍然可以阻止你的UI线程,因为await client.GetAsync(address)需要时间来创建一个任务传递给ConfigureAwait(false) 。 而你的耗时的操作可能会返回任务之前已经开始。

一个可能的解决方案是使用SynchronizationContextRemover从这里 :

public async Task<HtmlDocument> LoadPage(Uri address)
{
    await new SynchronizationContextRemover();

    using (var client = new HttpClient())
    using (var httpResponse = await client.GetAsync(address))
    using (var responseContent = httpResponse.Content)
    using (var contentStream = await responseContent.ReadAsStreamAsync())
        return LoadHtmlDocument(contentStream); //CPU-bound
}


文章来源: What are the differences between using ConfigureAwait(false) and Task.Run?