问题描述
我实现了一个具有控制器的Api,该控制器具有如下所示的调用树。
public async Task<Collection<United.Service.Presentation.LoyaltyModel.Program>> GetRewardPrograms(string languageCode)
{
return await _referenceDataDomain.GetRewardPrograms(languageCode).ConfigureAwait(false);
}
public async Task<Collection<Program>> GetRewardPrograms(string languageCode)
{
return await _referenceDataProvider.GetRewardPrograms(languageCode).ConfigureAwait(false);
}
public async Task<Collection<Program>> GetRewardPrograms(string languageCode)
{
if (string.IsNullOrEmpty(languageCode))
{
languageCode = _constants.LANGUAGE_CODE_EN_US;
}
var rewardProgramsSet = new Collection<Program>();
var format = CacheKeysDictionary.CacheKeyFormat(CacheKeysDictionary.RewardPrograms);
var cacheKey = string.Format(format,languageCode);
var cacheValue = await _cacheUtility.GetCacheItemAsync<Collection<Program>>(cacheKey).ConfigureAwait(false);
if (cacheValue != null && cacheValue.Any())
return cacheValue;
if (_commonConfig.UseLoyaltyService())
{
try
{
var cslHttpClient = _serviceProvider.GetrequiredService<IcslServiceProxy>();
var queryStringParams = new NameValueCollection() { { "languageCode",languageCode } };
var result = await cslHttpClient.GetAsync<NameValueCollection,RewardProgramsReferenceData>(_commonConfig.LoyaltyServiceUrl(),"ReferenceDataRewardProgram/idType/a",queryStringParams,_commonConfig.TimeOutDefault());
if (result != null && result.ResponseData != null && result.ResponseData.referenceDataRewardProgramList.Count > 0)
{
foreach (var item in result.ResponseData.referenceDataRewardProgramList)
{
var program = new Program
{
ProgramID = item.ProgramID.ToInt32(),Code = item.ProgramCode,Description = item.Description,Language = new Language { LanguageCode = languageCode }
};
rewardProgramsSet.Add(program);
}
}
}
catch { }
}
if (rewardProgramsSet != null && rewardProgramsSet.Any())
{
await _cacheUtility.SetCacheItemAsync(cacheKey,rewardProgramsSet).ConfigureAwait(false);
}
return rewardProgramsSet;
}
我收到一个代码审查反馈,因为正在使所有方法都异步,并且第二段代码未执行任何异步操作,所以我应该返回任务而不是使用异步方法,因为添加异步会在内部使我的方法进入状态机,并且造成一些性能问题,审稿人向我推荐了这篇文章 https://medium.com/@deep_blue_day/long-story-short-async-await-best-practices-in-net-1f39d7d84050,如果上述方法存在缺陷,请有人指导我。
解决方法
我通过斯蒂芬https://blog.stephencleary.com/2016/12/eliding-async-await.html发表的这篇文章得到了答案,感谢乔纳森(Jonathan)提供的链接
以下链接中的以下段落是我的问题的答案:
推荐准则 我建议遵循以下准则:
默认情况下不逃避。使用异步并等待自然的,易于阅读的代码。 当方法只是传递或重载时,请考虑取消选择。
// Simple passthrough to next layer: elide.
Task<string> PassthroughAsync(int x) => _service.PassthroughAsync(x);
// Simple overloads for a method: elide.
async Task<string> OverloadsAsync(CancellationToken cancellationToken)
{
... // Core implementation,using await.
}
Task<string> OverloadsAsync() => OverloadsAsync(CancellationToken.None);
// Non-trivial passthrough: use keywords.
async Task<string> PassthroughAsync(int x)
{
// Reasoning: GetFirstArgument can throw.
// Even if it doesn't throw today,some yahoo can change it tomorrow,and it's not possible for them to know to change *this* method,too.
return await _service.PassthroughAsync(GetFirstArgument(),x);
}
// Non-trivial overloads for a method: use keywords.
async Task<string> OverloadsAsync()
{
// Same reasoning as above; GetDefaultCancellationTokenForThisScope can throw.
return await OverloadsAsync(GetDefaultCancellationTokenForThisScope());
}