Ich mache gerade eine große Umgestaltung / Geschwindigkeitsoptimierung einer meiner größeren MVC-Apps durch. Es wird seit einigen Monaten in der Produktion bereitgestellt, und es kam zu Zeitüberschreitungen, die auf Verbindungen im Verbindungspool warteten. Ich habe das Problem auf die Verbindungen zurückgeführt, die nicht ordnungsgemäß entsorgt wurden.
Vor diesem Hintergrund habe ich diese Änderung an meinem Basis-Controller vorgenommen:
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);
}
}
Jetzt habe ich zwei Fragen:
- Führe ich eine Rennbedingung ein? Da das
configManager
verwaltetDataContext
, dasIQueryable<>
Parameter für die Ansichten verfügbar macht, muss ich sicherstellen, dassDispose()
diese nicht auf dem Controller aufgerufen werden, bevor die Ansicht das Rendern beendet. - Ruft das MVC-Framework
Dispose()
den Controller vor oder nach dem Rendern der Ansicht auf? Oder überlässt das MVC-Framework dies dem GarbageCollector?
asp.net-mvc
linq-to-sql
garbage-collection
idisposable
John Gietzen
quelle
quelle
Antworten:
Entsorgen Sie wird aufgerufen , nachdem die Ansicht gerendert wird, immer .
Die Ansicht wird im Aufruf von gerendert
ActionResult.ExecuteResult
. Das heißt (indirekt) vonControllerActionInvoker.InvokeAction
, was wiederum von genannt wirdControllerBase.ExecuteCore
.Da sich der Controller beim Rendern der Ansicht im Aufrufstapel befindet, kann er dann nicht entsorgt werden.
quelle
Nur um Craig Stuntz 'Antwort zu erweitern :
Die ControllerFactory behandelt, wenn ein Controller entsorgt wird. Bei der Implementierung der IControllerFactory-Schnittstelle muss unter anderem ReleaseController implementiert werden.
Ich bin nicht sicher, welche ControllerFactory Sie verwenden, ob Sie Ihre eigene gerollt haben, aber in Reflector, das die DefaultControllerFactory betrachtet, wird die ReleaseController-Methode folgendermaßen implementiert:
Eine IController-Referenz wird übergeben. Wenn dieser Controller IDisposable implementiert, wird die Dispose-Methode des Controllers aufgerufen. Wenn Sie also etwas haben, das Sie entsorgen müssen, nachdem die Anforderung abgeschlossen ist, dh nachdem die Ansicht gerendert wurde. Erben Sie IDisposable ab und setzen Sie Ihre Logik in die Dispose-Methode, um alle Ressourcen freizugeben.
Die ReleaseController-Methode wird vom System.Web.Mvc.MvcHandler aufgerufen, der die Anforderung verarbeitet und IHttpHandler implementiert. Die ProcessRequest verwendet den ihr zugewiesenen HttpContext und startet den Prozess zum Finden des Controllers, der die Anforderung verarbeitet, indem sie die implementierte ControllerFactory aufruft. Wenn Sie in die ProcessRequest-Methode schauen, sehen Sie den finally-Block, der den ReleaseController der ControllerFactory aufruft. Dies wird nur aufgerufen, wenn der Controller ein ViewResult zurückgegeben hat.
quelle
HttpContext
ist ein Mann? Jetzt bin ich wirklich verwirrt.