[C# 동시성 프로그래밍] - 일정 시간 동안 일시 정지
- C#/C# 문법
- 2022. 5. 8. 17:47
참고
- C# 동시성 프로그래밍
문제점
- 비동기적으로 일정 시간을 기야려야 합니다.
- 단위 테스트 또는 재시도 지연을 구현할 때 흔한 상황입니다.
- 간단한 타임아웃을 코딩할 때 필요하기도 합니다.
해법
- Task 형식에 들어 있는 정적 메서드 Delay는 지정한 시간 뒤에 완료하는 작업을 반환합니다.
- 다음 예제는 비동기적으로 완료하는 작업을 정의합니다.
- 비동기 작업의 구색을 갖추려면 동기적 성공, 비동기적 성공은 물론 비동기적 실패도 시험해야 합니다.
- 다음 예제는 비동기적 성공 사례에 쓰이는 작업을 반환합니다.
async Task<T> DelayResult<T>(T result, TimeSpan delay)
{
await Task.Delay(delay);
return result;
}
- 지수 백오프는 재시도 사이의 지연 시간을 점점 늘리는 전략으로 웹 서비스 관련 작업에 사용하면 서버가 재시도로 넘치지 않게 막을 수 있습니다.
- 다음 예제는 지수 백오프의 간단한 구현입니다.
async Task<string> DownloadStringWithRetries(HttpClient client, string uri)
{
// 1초 후, 다음에는 2호 후, 그 다음에는 4초 후, 이런식으로 재시도
TimeSpan nextDelay = TimeSpan.FromSeconds(1);
for(int i = 0; i != 3; ++i)
{
try
{
return await client.GetStringAsync(uri)
}
catch
{
}
await Task.Delay(nextDelay);
nextDelay = nextDelay + nextDelay;
}
return await client.GetStringAsync(uri);
}
실제 제품이라면, Polly NuGet 라이브러리를 사용하는 것을 추천합니다.
- 또한 Task.Delay는 간단한 타임아웃으로도 쓸 수 있습니다.
- CancallationTokenSource는 타임아웃 구현에 쓰이는 일반적인 형식입니다.
- 무한히 대기하는 Task.Delay 안에 취소 토큰을 넣으면 정해진 시간 뒤에 취소할 타임아웃 작업을 만들 수 있습니다.
async Task<string> DownloadStringWithTimeout(HttpClient client, string uri)
{
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
Task<string> downloadTask = client.GetStringAsync(uri);
Task timeoutTask = Task.Delay(Timeout.InfiniteTimeSpan, cts.Token);
Task completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if(completedTask == timeoutTask)
return null;
return await downloadTask;
}
- Task.Delay를 소프트 타임아웃으로 쓸 수는 있지만 한계가 있습니다.
- 타임아웃을 넘겨도 작업을 취소하지 않기 때문에 앞의 예제에서 다운로드 작업은 다운로드를 계속하며 따로 작업을 삭제하지 않으면 모든 응답을 다운로드 합니다.
- 더 좋은 방법은 취소 토큰을 타임아웃으로 사용해서 예제의 GetStringAsync와 같은 작업에 직접 전달하는 것 입니다.
- 즉 취소할 수 없는 작업이 있으면 다른 코드에서 Task.Delay를 사용해서 원래 작업의 타임아웃처럼 사용할 수 있습니다.
결론
- Task.Delay는 비동기 코드의 단위 테스트 또는 재시도 로직 구현에 좋은 선택입니다.
- 하지만, 타임아웃 구현에는 CancellationToekn 사용을 권장합니다.
728x90
'C# > C# 문법' 카테고리의 다른 글
[C# 동시성 프로그래밍] 완료한 작업 반환 (0) | 2022.05.12 |
---|---|
[C#] C# Mapster 사용법 (0) | 2022.05.11 |
[C# 동시성 프로그래밍] - 동시성 프로그래밍 개념 정리 (0) | 2022.05.07 |
[C# 문법] C# StringBuilder 성능 개선 (0) | 2022.04.28 |
[C# 문법] .NET 콘솔 서비스 - DockerFile, Imgae, Containger 생성하기 (0) | 2022.03.18 |
이 글을 공유하기