我目前正在开发一个自定义的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
}
这是一个不可重用的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);
}
}
这是正确的模式吗?或者我离开了?
它似乎工作(我没有得到任何错误或奇怪的行为),但在将其投入生产之前,我想与在编写这些Http处理程序方面比我有更多经验的人验证..
提前致谢!
答案 0 :(得分:4)
通常,对于异步模式,您应该使用传递给BeginXxx方法的state参数作为最后一个参数(您将其称为extraData
)。
因此,您可能希望创建一个包含(原始)extraData
的辅助类以及处理请求结束所需的任何其他状态。
但是,在您的具体情况下,我相信您并没有使用异步模式加速任何事情。虽然它有效,但它基本上只会增加开销,因为你以异步方式调用委托,除了调用线程池来处理调用之外什么都不做。因此,只要您没有多个代理通过异步调用同时运行,您就不会受益太多。由于Web请求已经是多线程的,我认为这不会有助于提高性能;相反,你遇到线程池饥饿的风险。
正确有效的异步处理并不容易。如果您正在执行固有的异步操作,例如从文件或网络连接读取数据,或者在调用支持异步调用的外部组件(例如Web服务调用或数据库)时,您可以从中受益。
答案 1 :(得分:2)
如果我没记错的话,IsReusable会向ASP.NET表明在处理请求后不应销毁您的处理程序,并且可以使用相同的实例来处理后续请求。即处理程序对象的一个实例不会同时处理多个请求。