大規模なMVCアプリの1つの大きなリファクタリング/速度調整を行っています。数か月前から実稼働環境にデプロイされており、接続プール内の接続を待機するタイムアウトが発生し始めていました。接続が適切に破棄されないまで問題を追跡しました。
それを踏まえて、ベースコントローラにこの変更を加えました。
_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);
}
}
_
今、私は2つの質問があります:
configManager
は、ビューに_IQueryable<>
_パラメーターを公開するDataContext
を管理するため、Dispose()
は、ビューがレンダリングを完了する前にコントローラーで呼び出されません。Dispose()
を呼び出しますか?または、MVCフレームワークはそれをGarbageCollectorに任せますか?Disposeは、ビューがレンダリングされた後に呼び出されますalways。
ビューは、ActionResult.ExecuteResult
の呼び出しでレンダリングされます。これはControllerActionInvoker.InvokeAction
によって(間接的に)呼び出され、ControllerBase.ExecuteCore
によって呼び出されます。
ビューがレンダリングされるとき、コントローラーは呼び出しスタック内にあるため、破棄することはできません。
Craig Stuntz's Answer を展開するだけです:
ControllerFactoryは、コントローラーが破棄されたときに処理します。 IControllerFactoryインターフェイスを実装する場合、実装する必要があるメソッドの1つはReleaseControllerです。
自分がどのControllerFactoryを使用しているか、自分でロールしたかどうかはわかりませんが、DefaultControllerFactoryを見るReflectorでは、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を返したときにのみ呼び出されます。