我正在对我的一个较大的 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?
总是在视图渲染后调用 Dispose。
视图在对 ActionResult.ExecuteResult
的调用中呈现。这由 ControllerActionInvoker.InvokeAction
(间接)调用,而后者又由 ControllerBase.ExecuteCore
调用。
由于在渲染视图时控制器在调用堆栈中,因此无法释放它。
只是为了扩展 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 时调用。
HttpContext
是男性?现在我真的很困惑。
不定期副业成功案例分享