방프리

24.03.12 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 34) 본문

C#/More Effective C#

24.03.12 Chapter3. 태스크 기반 비동기 프로그래밍 (Item 34)

방프리 2024. 3. 12. 23:09

Item 34 : 비동기 메서드의 반환값을 캐시하는 경우 ValueTask<T>를 사용하라

 

Task는 사용될 때마다 Task 인스턴스를 생성한다. 이조차도 비용이 될 수도 있고 만약 자주 호출되는 API일 경우
호출 될 때마다 계산하여 가져와야 하는 데이터라면 연산량을 줄이기 위해 결과값을 미리 캐싱하는 경우가 있다.

이 결과값을 비동기 메서드로 가져올 때 ValueTask가 빛을 발휘한다.

public ValueTask<IEnumerable<WeatherData>> RetrieveHistoricalData()
{
    if (DateTime.Now - lastReading > TimeSpan.FromMinutes(5))
    {
        return new ValueTask<IENumerable<WeatherData>>(recentObservations);
    }
    else
    {
        async Task<IEnumerable<WeatherData>> loadCache()
        {
            recentObservations = new List<WeatherData>();
            var observationDate = this.startDate;
            while (observationDate < this.endDate)
            {
                var observation = await 
                    RetrieveObservationData(observationDate);
                recentObservations.Add(observation);
                observationDate += TimeSpan.FromDays(1);
            }
            lastReading = DateTime.Now;
            return recentObservations;
        }
        return new ValueTask<IEnumerable<WeatherData>>(loadCache());
    }
}

그런데 결국 ValueTask 또한 객체를 생성하며 기존 Task 형태가 아니기 때문에 Task.WhenAll 같은 메서드를 사용할 경우
AsTask()로  한 번 더 변환해야하는 오버헤드가 있을 수 있다.

Comments