可重用异步HttpHandler的模式

Rem*_*Ros 6 c# asp.net asynchronous httphandler ihttpasynchandler

我目前正在开发一个自定义的HttpHandler(用于压缩/组合CSS,但这对于这个问题无关紧要).

我从一个简单的reusable = true同步HttpHandler开始,就像我们都知道的那样.

现在我正在尝试将其改进为异步处理程序(因为它使用IO功能并且它在非常繁忙的网站上使用).

我的第一次尝试(这似乎工作正常):

Action<HttpContext> asyncProcessRequest;

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
    asyncProcessRequest = new Action<HttpContext>(ProcessRequest);
    return asyncProcessRequest.BeginInvoke(context, cb, extraData);
}

public void EndProcessRequest(IAsyncResult result)
{
    asyncProcessRequest.EndInvoke(result);
}

public virtual void ProcessRequest(HttpContext context)
{
    // real work
}
Run Code Online (Sandbox Code Playgroud)

这是一个不可重用的httphandler(从我读到的,IsReusable应该是false,因为这个处理程序有状态(asyncProcessRequest字段).

现在我想让它重复使用.所以我的第一个想法是创建一个IAsyncResult/Action字典,如下所示:

IDictionary<IAsyncResult, Action<HttpContext>> asyncProcessRequests;

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
    if (asyncProcessRequests == null)
    {
        asyncProcessRequests = new Dictionary<IAsyncResult, Action<HttpContext>>();
    }

    var request = new Action<HttpContext>(ProcessRequest);
    var result = request.BeginInvoke(context, cb, extraData);
    asyncProcessRequests.Add(result, request);
    return result;
}

public void EndProcessRequest(IAsyncResult result)
{
    Action<HttpContext> action;
    if (asyncProcessRequests.TryGetValue(result, out action))
    {
        action.EndInvoke(result);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是正确的模式吗?还是我离开了?

它似乎工作(我没有得到任何错误或奇怪的行为),但在将其投入生产之前,我想与在编写这些Http处理程序时比我有更多经验的人验证..

提前致谢!

Luc*_*ero 4

一般来说,对于异步模式,您应该使用传递给 BeginXxx 方法的状态参数作为最后一个参数(您称之为extraData)。

因此,您可能想要创建一个辅助类来保存(原始)extraData以及处理请求结束所需的任何其他状态。

但是,在您的具体情况下,我相信您不会使用异步模式来加速任何事情。虽然它有效,但它基本上只会增加开销,因为您以异步方式调用委托,它除了分派对线程池的调用来处理调用之外什么也不做。因此,只要您没有通过异步调用同时运行多个委托,您就不会受益匪浅。由于网络请求已经是多线程的,我认为这不会有助于性能;相反,您会遇到线程池饥饿的风险。

正确且高效的异步处理并不容易。如果您正在执行本质上异步的操作,例如从文件或网络连接读取数据,或者调用支持异步调用的外部组件(例如 Web 服务调用或数据库),您可以从中受益。

  • 是的,如果您只计划异步调用委托。如果您正在执行冗长的文件、网络(包括 Web 请求)或数据库调用,请考虑实现异步模式,否则不要实现。另请参阅http://msdn.microsoft.com/en-us/magazine/cc164128.aspx (3认同)