Ваш первый не сработает.Самое простое и наиболее подходящее из них:
public async Task<T> GetValueAsync<T>(string key)
{
if (_cache.ContainsKey(key))
{
return _cache.GetItem(key);
}
T result = await _api.GetValueAysnc(key);
_cache.Add(key, result);
return result;
}
Или еще лучше, если это возможно:
public async Task<T> GetValueAsync<T>(string key)
{
if (_cache.TryGet(key, out T result))
{
return result;
}
result = await _api.GetValueAysnc(key);
_cache.Add(key, result);
return result;
}
Это отлично работает и вернет уже выполненное задание.если значение находилось в кеше, то await
будет немедленно продолжено.
Однако , если значение находится в кеше большую часть времени и метод вызывается достаточно часто, чтобы дополнительное устройство около async
имело значение, тогда его можно полностью избежать в таком случае:
public Task<T> GetValueAsync<T>(string key)
{
if (_cache.TryGet(key, out Task<T> result))
{
return result;
}
return GetAndCacheValueAsync(string key);
}
private async Task<T> GetAndCacheValueAsync<T>(string key)
{
var task = _api.GetValueAysnc(key);
result = await task;
_cache.Add(key, task);
return result;
}
Здесь, если значение кэшируется, мы избегаем как конечного автоматавокруг async
, а также создание нового Task<T>
, поскольку мы сохранили фактическое Task
.Каждый из них выполняется только в первом случае.