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

时间:2009-09-04 15:41:02

标签: asp.net-mvc linq-to-sql garbage-collection idisposable

我正在对我的一个较大的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() 观点,我需要确保不会调用Dispose() 在视图完成渲染之前在控制器上。
  2. 在呈现视图之前或之后,MVC框架是否在Controller上调用{{1}}?或者,MVC框架是否会离开 直到GarbageCollector?

2 个答案:

答案 0 :(得分:67)

在渲染视图后调用Dispose,始终

视图在ActionResult.ExecuteResult的调用中呈现。这是ControllerActionInvoker.InvokeAction(间接)调用的,ControllerBase.ExecuteCore又调用了{{1}}。

由于在渲染视图时控制器位于调用堆栈中,因此无法处理它。

答案 1 :(得分:36)

只需展开Craig Stuntz's Answer

ControllerFactory处理Controller的处理时间。在实现IControllerFactory接口时,需要实现的方法之一是ReleaseController。

我不确定您使用的是什么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块。仅在Controller返回ViewResult时调用此方法。