Я прохожу большой рефакторинг / настройку скорости одного из моих больших приложений 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
управляет тем,DataContext
что предоставляетIQueryable<>
параметры представлениям, мне нужно убедиться, чтоDispose()
он не будет вызван на контроллере до того, как представление завершит рендеринг. - Обращается ли среда MVC
Dispose()
к контроллеру до или после визуализации представления? Или структура MVC оставляет это на усмотрение GarbageCollector?
asp.net-mvc
linq-to-sql
garbage-collection
idisposable
Джон Гитцен
источник
источник
Ответы:
Dispose всегда вызывается после рендеринга представления .
Представление отображается при вызове
ActionResult.ExecuteResult
. Это называется (косвенно) byControllerActionInvoker.InvokeAction
, который, в свою очередь, вызываетControllerBase.ExecuteCore
.Поскольку при рендеринге представления контроллер находится в стеке вызовов, его нельзя удалить.
источник
Просто чтобы расширить ответ Крейга Стунца :
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, вы увидите блок finally, который вызывает ReleaseController ControllerFactory. Это вызывается только тогда, когда контроллер возвратил ViewResult.
источник
HttpContext
это мужчина? Теперь я действительно запутался.