C# 7 : async 커스텀 리턴 타입
지금까지의 async / await는 void, Task, Task<T> 등 3가지 리턴 타입만을 가질 수 있었는데,
Task는 리턴값이 없는 비동기 메서드를 위해서 사용되었고, Task<T>는 리턴값 T를 갖는 비동기 메서드를 위해 사용되었다.
void는 주로 이벤트핸들러를 위해 사용되었지만 메서드 내부에서 Unhandled Exception이 발생하면 프로세스를 다운시키는 문제가 있어서 사용을 자제한 리턴타입이다.
C# 7 에서는 이러한 3가지 async 리턴타입에 대한 제약을 넘어 커스텀 리턴 타입을 허용하게 되었는데, 이러한 커스텀 타입은 async 패턴에 맞게 정의되어야 한다.
이러한 Custom 리턴 타입의 하나로 .NET Framework에서 ValueTask<T> 라는 타입이 제공되고 있는데,
필요한 경우 Nuget 패키지에서 System.Threading.Tasks.Extensions 을 설치하여 사용한다.
C# 7 : ValueTask<T>
async 메서드에서 흔히 사용하는 Task, Task<T> 리턴타입은 비동기 처리가 필요없이 상수값을 리턴할 때도
Task 객체를 항상 만들기 때문에 일부 경우에 성능을 저하시킬 수 있다.
ValueTask<T> 타입은 값 T 와 Task<T> 가 결합된 형태라고 볼 수 있는데, async 메서드 내에서 동기 처리가 필요할 때는 Task 객체를 생성하지 않고 직접 값 T 를 리턴하고,
비동기 처리가 필요할 때는 Task 객체를 생성하여 사용하게 된다.
따라서, ValueTask<T> 타입은 async 메서드 내에 동기 처리와 비동기 처리가 혼합되어 있을 때 유용하다.
예를 들어, async 메서드가 캐쉬에 데이타가 있으면 즉시 동기적으로 캐쉬값을 리턴하고
그렇지 않으면 네트워크을 통해 비동기적으로 값을 가져와야 하는 경우, async 리턴타입으로 ValueTask<T>을 사용하면 성능 향상을 기대할 수 있다.
아래 예제는 캐쉬를 사용하여 동기와 비동기 처리를 함께 수행하는 async 메서드에 대한 예로서 리턴타입으로 ValueTask<T> 커스텀 타입을 사용하고 있다.
(여기서 ValueTask 대신 Task를 써도 동작하지만 ValueTask이 더 효율적이다)
예제
private Dictionary<int, int> cache = new Dictionary<int, int>();
private async ValueTask<int> GetCache(int id)
{
if (cache.ContainsKey(id))
{
// 동기 처리. 값 직접 리턴
return cache[id];
}
else
{
// 비동기 처리. Task 객체 생성
int res = await Fetch(id);
cache.Add(id, res);
return res;
}
}
본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.