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
}
'development' 카테고리의 다른 글
OpenCV C ++에서 (Mat) 행렬의 값을 인쇄합니다. (0) | 2021.01.07 |
---|---|
ScheduledExecutorService에서 작업을 제거하는 방법은 무엇입니까? (0) | 2021.01.07 |
Linux 플랫폼 드라이버와 일반 장치 드라이버의 차이점은 무엇입니까? (0) | 2021.01.07 |
Python-TypeError : 'int'개체는 반복 할 수 없습니다. (0) | 2021.01.07 |
Docker 컨테이너에서 실행되는 Tomcat 8에 Java webapp 배포 (0) | 2021.01.07 |