ChatGPT解决这个技术问题 Extra ChatGPT

ASP MVC:何时调用 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);
    }
}

现在,我有两个问题:

我是否引入了比赛条件?由于 configManager 管理向视图公开 IQueryable<> 参数的 DataContext,因此我需要确保在视图完成渲染之前不会在控制器上调用 Dispose()。 MVC 框架是在视图渲染之前还是之后在 Controller 上调用 Dispose()?或者,MVC 框架是否将其留给 GarbageCollector?

我很期待这个答案!好问题!
无需查看其他代码(您的或 ASP.NET MVC 的..),您究竟为什么需要取消 configManager?这有什么帮助吗?在你们任何人“DUH”我之前仔细考虑一下。
我的意思是在一般情况下,可以像这样轻松删除竞争条件。在这种特殊情况下,我怀疑一个控制器实例会被多个线程使用,因此不存在任何竞争条件的风险。
@Andrei:这只是一些防御性编码。如果我的 dispose 方法被调用两次,它会阻止我两次处理数据库连接。
@Andrei:好吧,在我看来,“忽略”和“无论如何调用子对象的处置”是完全不同的。因此检查。

A
Amirhossein Mehrvarzi

总是在视图渲染后调用 Dispose。

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

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


太好了,你有文件吗?我只是想确定一下。
伟大的!找到解释它的文档会很棒。但是扩展的答案确实令人欣慰。代码是更好的文档。 :D
C
Community

只是为了扩展 Craig Stuntz's Answer

ControllerFactory 在处理控制器时进行处理。在实现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 块。这仅在控制器返回 ViewResult 时调用。


很棒的答案。我无法弄清楚为什么 Controller 对象的直接实例不允许我在其上调用 Dispose(),但看起来我需要使用 IDisposable 接口创建它的新实例。这对我有用!
所以... HttpContext 是男性?现在我真的很困惑。