development

ConfigureAwait (false)와 Task.Run 사용의 차이점은 무엇입니까?

big-blog 2021. 1. 7. 20:37
반응형

ConfigureAwait (false)와 Task.Run 사용의 차이점은 무엇입니까?


후속 코드가 UI 스레드 일 수있는 호출자의 실행 컨텍스트에서 실행되지 않도록 라이브러리 코드에서 s 를 사용 ConfigureAwait(false)하는 것이 좋습니다 await. 나는 또한 같은 이유로 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
        });
}

이 두 접근 방식의 차이점은 무엇입니까?


라고 말하면 Task.Run시간이 오래 걸릴 수있는 CPU 작업이 있으므로 항상 스레드 풀 스레드에서 실행되어야합니다.

이라고 말하면 ConfigureAwait(false)나머지 async메서드에는 원래 컨텍스트가 필요하지 않다는 것입니다. ConfigureAwait최적화 힌트에 가깝습니다. 항상 스레드 풀 스레드에서 연속이 실행되는 것은 아닙니다 .


이 경우 Task.Run첫 번째 await 호출 ( await client.GetAsync(address))이 호출 결과와 마찬가지로 호출 컨텍스트로 다시 마샬링 되므로 버전에 약간 더 많은 오버 헤드 가 발생합니다 Task.Run.

반면에 첫 번째 예제에서 첫 번째 Async()메서드는 호출 컨텍스트로 다시 마샬링 할 필요가 없도록 구성되어 있으므로 계속이 백그라운드 스레드에서 계속 실행될 수 있습니다. 따라서 호출자의 컨텍스트로 다시 마샬링되지 않습니다.


동의 @Stephen 답변, 여전히 혼란 스러우면 아래 스크린 샷을 참조하십시오. 1 # ConfigureAwait없이 (false)
아래 이미지 참조 레이블을 업데이트하려는 메인 스레드여기에 이미지 설명 입력

2 # With ConfigureAwait (false)
레이블 업데이트를 시도하는 아래 이미지 작업 스레드 참조여기에 이미지 설명 입력


참고로, 두 경우 모두 에 전달할 작업을 만드는 데 시간이 필요 하기 때문에 UI 스레드를 계속 차단할LoadPage()있습니다 . 시간이 많이 걸리는 작업은 작업이 반환되기 전에 이미 시작되었을 수 있습니다.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
}

참조 URL : https://stackoverflow.com/questions/14906092/what-are-the-differences-between-using-configureawaitfalse-and-task-run

반응형