1

我们正在将所有或大部分 .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 successand的输出参数string message;但似乎这可以使用Tuple<>;以体面和快速的方式完成。否则我们可以创建一个返回类型模型。

要正确地做到这一点,将有数百种重构方法;相当的一项事业。

  1. 这会按预期工作,并且是实现目标的最佳解决方案吗?
  2. 是否值得付出所有必要的努力,最终目标是提高 Web 服务器的可扩展性和随后的“性能”?
4

2 回答 2

4

是否值得创建一个公开可等待任务返回类型的异步辅助方法?

提议是创建一个如下的辅助方法

这只是将内存中的工作排队到线程池中。

(旁注:永远不应该使用任务构造函数。永远。如果您需要将工作排队到线程池,请使用Task.Run代替任务构造函数Start

这会按预期工作,并且是实现目标的最佳解决方案吗?

是否值得付出所有必要的努力,最终目标是提高 Web 服务器的可扩展性和随后的“性能”?

这些是同一个问题。目标是可扩展性;异步只是帮助您完成它的一种方法。

异步有助于 ASP.NET 上的可伸缩性,因为它释放了可以处理其他请求的线程。但是,如果您使用另一个线程创建异步方法,那么这对您毫无帮助。我称之为“假异步”——这些方法看起来是异步的,但实际上它们只是在线程池上同步运行。

与真正的异步相比,假异步实际上会损害您的可扩展性。

于 2016-09-15T21:25:00.923 回答
1

因为这是一个内存缓存,我这么说是出于对 NCache 的任何直接经验,但对其他缓存系统的经验。

  1. 是的,这当然可以。我宁愿选择允许我定义我的响应类型(如果可能的话)的响应结构或通用类。元组还不错,如果您选择类,可能会更好。但他们的眼睛并不容易。
  2. 现在,当谈到性能时,有一个问题。这是为您准备的缓存服务器,您当然想要快速读写。访问内存缓存应该很容易。当你在这里直接访问内存时,从性能的角度来看,它并不会真正给你太多。您是否确保您的代码是完全异步的,并且您正在正确使用线程池以使事情顺利进行?是的,当然,但它所做的只是在您访问缓存时添加一个额外的层或工作。
  3. 当您要进行异步时,请确保您的内存缓存是线程安全的。:)
于 2016-09-15T21:09:20.840 回答