什么时候调用 IController Dispose() ?

我正在对我的一个更大的 MVC 应用程序进行重大的重构/速度调整。现在,它已经部署到生产环境几个月了,我开始在连接池中等待连接的时候出现超时。我已经追踪到问题的连接没有得到正确处理。

有鉴于此,我对我的基本控制器做了以下更改:

public class MyBaseController : Controller
{
private ConfigurationManager configManager;  // Manages the data context.


public MyBaseController()
{
configManager = new ConfigurationManager();
}


protected override void Dispose(bool disposing)
{
if (disposing)
{
if (this.configManager != null)
{
this.configManager.Dispose();
this.configManager = null;
}
}


base.Dispose(disposing);
}
}

现在,我有两个问题:

  1. 我是否引入了竞态条件? 因为 configManager管理将 IQueryable<>参数暴露给 观点,我需要确保 Dispose()将不会被称为 在视图完成渲染之前在控制器上。
  2. MVC 框架是在渲染视图之前还是之后在 Controller 上调用 Dispose()?或者,MVC 框架留下了 到垃圾收集器
28687 次浏览

Dispose is called after the view is rendered, always.

The view is rendered in the call to ActionResult.ExecuteResult. That's called (indirectly) by ControllerActionInvoker.InvokeAction, which is in turn called by ControllerBase.ExecuteCore.

Since the controller is in the call stack when the view is rendered, it cannot be disposed then.

Just to expand on Craig Stuntz's Answer:

The ControllerFactory handles when a Controller is disposed. When implementing the IControllerFactory interface, one of the methods that needs to be implemented is ReleaseController.

I am not sure what ControllerFactory you are using, whether you rolled your own, but in Reflector looking at the DefaultControllerFactory, the ReleaseController method is implemented like so:

public virtual void ReleaseController(IController controller)
{
IDisposable disposable = controller as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}

An IController reference is passed in, if that controller implements IDisposable, then that controllers Dispose method is called. So, if you have anything you need disposing after the request is finished, which is after the view is rendered. Inherit off of IDisposable and put your logic in the Dispose method to release any resources.

The ReleaseController method is called by the System.Web.Mvc.MvcHandler which handles the request and it implements IHttpHandler. The ProcessRequest takes the HttpContext given to it and starts the process of finding the controller to handle the request, by calling into the implemented ControllerFactory. If you look in the ProcessRequest method you will see the finally block which calls the ControllerFactory's ReleaseController. This is only called when the Controller has returned a ViewResult.