我们正在将所有或大部分.NET 4.6 MVC WebAPI控制器方法重构为async
方法。
对于具有较低级别调用等待方法(如SQL命令执行)的方法,这似乎很有效;但是我们正在使用Alachisoft的内存分布式缓存框架,名为NCache(确切地说是4.6 SP2),它不提供任何真正的异步方法。
是否值得创建一个async
辅助方法,以便公开一个等待的Task<object>
返回类型?
传统上使用NCache API,在以下用法中Get
Key
来自缓存的对象;
NCacheObject.Get(string);
建议是创建以下的辅助方法;
protected static async Task<Object> GetAsync(string key, Cache nCache)
{
Task<Object> getTask = new Task<Object>(() => nCache.Get(key));
getTask.Start();
return await getTask.ConfigureAwait(false);
}
这样它就可以允许async
方法的完全瀑布直到入口控制器方法;
public static async Task<Tuple<List<SomeModel>, bool, string>> GetSomeModelList(string apiKey)
{
return newTuple<List<SomeModel>, bool, string>(await GetAsync("GetSomeModelKey", CacheInstance).ConfigureAwait(false), true, "Success message");
}
最后是控制器方法;
[HttpGet, Route("Route/Method")]
public async Task<ResponseOutputModel<List<SomeModel>>> GetSomeModelList()
{
ResponseOutputModel<List<SomeModel>> resp = new ResponseOutputModel<List<SomeModel>>();
try
{
Tuple<List<SomeModel>, Boolean, String> asyncResp = await CacheProcessing.GetSomeModelList(GetApiKey()).ConfigureAwait(false);
resp.Response = asyncResp.Item1;
resp.Success = asyncResp.Item2;
resp.Message = asyncResp.Item3;
}
catch (Exception ex)
{
LoggingHelper.Write(ex);
resp.StatusCode = Enumerations.ApiResponseStatusCodes.ProcessingError;
resp.Success = false;
resp.Message = ex.Message;
}
return resp;
}
这会使重构变得复杂,因为原始方法实际上具有bool success
和string message
的输出参数;但似乎可以使用Tuple<>
以体面和快捷的方式完成;否则我们可以创建一个返回类型模型。
为了做到这一点,将有数百种重构方法;很有希望。
答案 0 :(得分:4)
是否值得创建一个异步帮助方法来公开一个等待的任务返回类型?
建议是创建以下
的帮助方法
这只是将内存中的工作排入队列。
(旁注:永远不应该使用任务构造函数。永远。如果需要将工作排队到线程池,请使用Task.Run
而不是Start
的任务构造函数
这是否符合预期,是实现目标的最佳解决方案?
是否值得花费所有必要的努力,最终目标是提高Web服务器的可扩展性和随后的“性能”?
这些都是同一个问题。目标是可扩展性;异步只是帮助你完成它的一种方法。
Asynchrony协助ASP.NET的可伸缩性,因为它释放了一个可以处理其他请求的线程。但是,如果您通过使用另一个线程来创建异步的方法,那么这根本不会对您有所帮助。我将此称为“假异步” - 这些方法看起来是异步的,但它们实际上只是在线程池上同步运行。
与真正的异步相比,虚假异步实际上会损害您的可扩展性。
答案 1 :(得分:1)
因为这是一个内存缓存,我说这是对NCache的任何直接经验,但与其他缓存系统的经验。