我们是否需要使所有方法异步

问题描述

我实现了一个具有控制器的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());
}