我最近对我的一个ASP.NET MVC3控制器进行了一些(相当简单的)更改,并将其中一个操作更改为异步操作。基本上我采用了这样的代码:
public ActionResult MyAction(BindingObject params){
// use HttpWebRequest to call an external API and process the results
}
并将其转换为如下代码:
private delegate ActionResult DoMyAction(BindingObject params);
public void MyActionAsync(BindingObject params){
AsyncManager.OutstandingOperations.Increment();
var doMyAction = new DoMyAction(MyAction);
doMyAction.BeginInvoke(params, MyActionCallback, doMyAction);
}
private void MyActionCallback(IAsyncResult ar){
var doMyAction = ar.AsyncState as DoMyAction;
AsyncManager.Parameters["result"] = doMyAction != null ? doMyAction.EndInvoke(ar) : null;
AsyncManager.OutstandingOperations.Decrement();
}
public ActionResult MyActionCompleted(ActionResult result){
return result;
}
private ActionResult MyAction(BindingObject params){
// use HttpWebRequest to call an external API and process the results
}
这似乎工作正常,当我在本地测试它调用MyAction时,每个方法中的断点会在我期望它们时触发它并最终返回预期结果。
我预计这种变化最多可以提高重负载下的性能,因为现在我的工作线程没有被等待HttpWebRequest调用外部API,最糟糕的是根本没有效果。
在推动此更改之前,我的服务器CPU使用率平均约为30%,而我的W3SVC_W3WP Active Requests perfmon stat在10-15左右徘徊。服务器是Win Server 2008 R2,MVC站点每秒大约有50个请求。
推动此更改后,CPU将持续90-100%的使用率,并且W3SVC_W3WP Active Requests计数器缓慢增加,直到达到最大值5000并保持在那里。该网站完全没有响应(超时或提供“服务不可用”错误)。
我的假设是我正在错误地实现AsyncController,缺少一些所需的额外配置,或者可能只是误解了AsyncController应该用于什么。无论如何,我的问题是为什么会发生这种情况?
答案 0 :(得分:1)
通过异步调用委托,您可以将工作移动到线程池。你仍然刻录一个线程。你什么也得不到,而且表现松散。
当你可以触发真正的异步IO时,异步很有意义。