asp.net-mvc ASP MVC:何时调用 IController Dispose()?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1380019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 23:49:33  来源:igfitidea点击:

ASP MVC: When is IController Dispose() called?

asp.net-mvclinq-to-sqlgarbage-collectionidisposable

提问by John Gietzen

I'm going through a big refactoring / speed tweaking of one of my larger MVC apps. It has been deployed to production for a few months now, and I was starting to get timeouts waiting for connections in the connection pool. I have tracked the issue down to the connections not getting disposed properly.

我正在对我的一个较大的 MVC 应用程序进行大规模重构/速度调整。它已经部署到生产中几个月了,我开始在连接池中等待连接超时。我已将问题追溯到未正确处理的连接。

In light of that, I have since made this change to my base controller:

有鉴于此,我已经对我的基本控制器进行了更改:

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);
    }
}

Now, I have two questions:

现在,我有两个问题:

  1. Am I introducing a race condition?Since the configManagermanages the DataContextthat exposes IQueryable<>parameters to the views, I need to make sure that Dispose()will not be called on the controller before the view finishes rendering.
  2. Does the MVC framework call Dispose()on the Controller before or after the view is rendered? Or, does the MVC framework leave that up to the GarbageCollector?
  1. 我是在引入竞争条件吗?由于configManager管理向视图DataContext公开IQueryable<>参数的 ,我需要确保Dispose()在视图完成渲染之前不会在控制器上调用。
  2. MVC 框架Dispose()是在渲染视图之前还是之后调用控制器?或者,MVC 框架是否将其留给 GarbageCollector?

采纳答案by Craig Stuntz

Dispose is called after the view is rendered, always.

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

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.

视图在对 的调用中呈现ActionResult.ExecuteResult。这称为(间接)由ControllerActionInvoker.InvokeAction,而后者又由 调用ControllerBase.ExecuteCore

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

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

回答by Dale Ragan

Just to expand on Craig Stuntz's Answer:

只是为了扩展Craig Stuntz 的回答

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

ControllerFactory 在处理 Controller 时进行处理。在实现 IControllerFactory 接口时,需要实现的方法之一是 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:

我不确定您使用的是什么 ControllerFactory,无论您是否使用自己的控制器,但是在 Reflector 中查看 DefaultControllerFactory,ReleaseController 方法的实现如下:

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.

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

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.

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