代码之家  ›  专栏  ›  技术社区  ›  John Gietzen

ASP MVC:何时调用IController Dispose()?

  •  79
  • John Gietzen  · 技术社区  · 15 年前

    我正在对我的一个更大的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 管理 DataContext 暴露的 IQueryable<> 参数到 视图,我需要确保 Dispose() 不会被调用 在视图完成渲染之前在控制器上。
    2. MVC框架是否调用 处置() 在呈现视图之前还是之后在控制器上?或者,MVC框架是否留下了 去垃圾回收站?
    2 回复  |  直到 9 年前
        1
  •  65
  •   Amirhossein Mehrvarzi GGregson    10 年前

    在呈现视图后调用Dispose, 总是 .

    在调用中呈现视图 ActionResult.ExecuteResult .这被(间接地)称为 ControllerActionInvoker.InvokeAction ,依次由调用 ControllerBase.ExecuteCore .

    由于在呈现视图时控制器位于调用堆栈中,因此无法在该时候释放它。

        2
  •  36
  •   Community CDub    7 年前

    只是为了扩大 Craig Stuntz's Answer :

    控制器工厂在释放控制器时进行处理。在实现IControllerFactory接口时,需要实现的方法之一是ReleaseController。

    我不确定您使用的是哪个ControllerFactory,您是否使用自己的ControllerFactory,但是在Reflector中,在查看DefaultControllerFactory时,ReleaseController方法是这样实现的:

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

    传入IController引用,如果该控制器实现IDisposable,则调用该控制器Dispose方法。因此,如果在请求完成后(即视图呈现之后)有任何需要处理的内容。从IDisposable继承并将逻辑放入Dispose方法以释放任何资源。

    releaseController方法由处理请求的system.web.mvc.mvchandler调用,并实现IHttphandler。processRequest接收给它的httpContext,并通过调用已实现的ControllerFactory来启动查找控制器以处理请求的过程。如果查看processRequest方法,您将看到调用ControllerFactory的ReleaseController的finally块。仅当控制器返回viewresult时才调用此函数。