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

Joh*_*zen 82 asp.net-mvc garbage-collection idisposable linq-to-sql

我正在对我的一个较大的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我有两个问题:

  1. 我是否介绍了竞争条件?由于configManager管理DataContextIQueryable<>参数公开给视图,我需要确保Dispose()在视图完成渲染之前不会在控制器上调用.
  2. MVC框架是否在Dispose()呈现视图之前或之后调用Controller?或者,MVC框架是否将其留给了GarbageCollector?

Cra*_*ntz 69

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

视图在调用中呈现ActionResult.ExecuteResult.这被称为(间接)ControllerActionInvoker.InvokeAction,而后者则被称为ControllerBase.ExecuteCore.

由于在呈现视图时控制器位于调用堆栈中,因此无法进行处理.


Dal*_*gan 37

只是为了扩展Craig Stuntz的答案:

ControllerFactory处理Controller何时被处理.实现IControllerFactory接口时,需要实现的方法之一是ReleaseController.

我不确定你使用的是什么ControllerFactory,无论你是自己编写的,但是在Reflector中查看DefaultControllerFactory,ReleaseController方法是这样实现的:

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

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

ReleaseController方法由System.Web.Mvc.MvcHandler调用,它处理请求并实现IHttpHandler.ProcessRequest获取给它的HttpContext,并通过调用实现的ControllerFactory开始寻找控制器来处理请求的过程.如果查看ProcessRequest方法,您将看到调用ControllerFactory的ReleaseController的finally块.仅在Controller返回ViewResult时调用此方法.