방프리
24.02.13 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 31) 본문
Item 31 : 불필요한 콘텍스트 마셜링을 피하라
어떤 콘텍스트에서도 실행될 수 있는 코드를 '자유 코드' 라고 한다. 기본적으로 개발자가 작성하는 코드는 콘텍스트 자유 코드이다. 반대로 특정 SynchronizationContext에서만 실행될 수 있는 코드를 '콘텍스트 인식코드'라고 한다.
콘텍스트 인식코드는 주로 GUI, HTTPContext 등에 사용되며 이 콘텍스트들은 다른 콘텍스트와 스위칭 되며 실행되도록 해야한다. 콘텍스트를 전환해서 문제를 피하는 것이 콘텍스트를 전환하지 않아 발생하는 문제를 해결하는 것보다 더 나은 선택이기 때문이다.
이를 위해 ConfigureAwait() 메서드를 사용한다.
public static async Task<XElement> ReadPacket(string url)
{
var result = await DownloadAsync(url)
.ConfigureAwait(continueOnCapturedContext: false);
return XElement.Parse(result);
}
주의할 점은 ConfigureAwait() 을 사용한다고 해서 모든 동작이 기본 콘텍스트에서 실행되진 않는다.
public static async Task<Config> ReadConfig(string url)
{
//하단 코드에서 비동기로 돌수도 있지만 동기적으로 돌 수도 있다.
var result = await DownloadAsync(url)
.ConfigureAwait(continueOnCapturedContext: false);
var item = XElement.Parse(result);
var userConfig = from node in items.Descendants()
where node.Name == "Config"
select node.Value;
var configUrl = userConfig.SingleOrDefault();
if (configUrl != null)
{
//상단의 코드가 동기적으로 돌았다면 하단의 구문은
//기본 콘텍스트가 아닌 캡쳐된 콘텍스트에서 동작할 수도 있다.
result = await DownloadAsync(configUrl)
.ConfigureAwait(continueOnCapturedContext: false);
var config = await ParseConfig(result)
.ConfigureAwait(continueOnCapturedContext: false);
return config;
}
else
{
return new Config;
}
}
private async void OnCommand(object sender, RoutedEventArgs e)
{
var viewModel = (DataContext as SampleViewModel);
try
{
//해당 부분에서 ConfigureAwait()가 없기에 예기지 못하게 앱이 죽거나
//효율적으로 콘텍스트가 동작하지 못함
Config config = await ReadConfigAsync(viewModel);
await viewModel.Update(config);
}
catch (Exception ex) when (logMessage(viewModel, ex))
{
}
}
public static async Task<Config> ReadConfig(string url)
{
//하단 코드에서 비동기로 돌수도 있지만 동기적으로 돌 수도 있다.
var result = await DownloadAsync(url)
.ConfigureAwait(continueOnCapturedContext: false);
var item = XElement.Parse(result);
var userConfig = from node in items.Descendants()
where node.Name == "Config"
select node.Value;
var configUrl = userConfig.SingleOrDefault();
if (configUrl != null)
{
//상단의 코드가 동기적으로 돌았다면 하단의 구문은
//기본 콘텍스트가 아닌 캡쳐된 콘텍스트에서 동작할 수도 있다.
result = await DownloadAsync(configUrl)
.ConfigureAwait(continueOnCapturedContext: false);
var config = await ParseConfig(result)
.ConfigureAwait(continueOnCapturedContext: false);
return config;
}
else
{
return new Config;
}
}
'C# > More Effective C#' 카테고리의 다른 글
24.03.11 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 33) (0) | 2024.03.11 |
---|---|
24.03.10 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 32) (0) | 2024.03.10 |
24.01.12 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 30) (2) | 2024.01.12 |
24.01.07 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 29) (0) | 2024.01.07 |
24.01.04 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 28) (0) | 2024.01.04 |
Comments