System.Web.Mvc中IControllerFactory创建的控制器未被释放的原因
控制器实例未释放的原因与修复方案
核心问题在于你只实现了IControllerFactory接口的CreateController方法,却没有实现ReleaseController方法,导致ASP.NET MVC框架无法正确回收控制器实例。
在ASP.NET MVC的请求生命周期中,默认控制器工厂(如DefaultControllerFactory)会在请求处理完成后,调用ReleaseController方法来完成控制器的资源清理:如果控制器实现了IDisposable接口,工厂会自动触发其Dispose方法,释放托管/非托管资源,同时让GC能够正常回收实例。而你的自定义SystemConfig类仅完成了控制器的创建逻辑,完全跳过了回收步骤,所以每个请求生成的控制器实例会一直驻留在内存中,直到应用池强制回收。
修复步骤
- 在
SystemConfig类中实现ReleaseController方法:
public class SystemConfig : IControllerFactory { // 已有的CreateController方法... public void ReleaseController(IController controller) { // 检查控制器是否实现IDisposable,若实现则调用Dispose if (controller is IDisposable disposable) { disposable.Dispose(); } } // 还需实现IControllerFactory的GetControllerSessionBehavior方法(如果是MVC 3及以上) public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName) { // 默认返回Default,可根据需求调整 return SessionStateBehavior.Default; } }
注:MVC 3及以上版本的IControllerFactory还要求实现GetControllerSessionBehavior方法,否则会编译报错。
- 确保控制器正确实现
IDisposable接口(若持有资源):
如果你的控制器(如AccountController)持有数据库上下文、文件句柄等需要手动清理的资源,要正确实现IDisposable:
public class AccountController : Controller, IDisposable { private readonly MyDbContext _dbContext; public AccountController(MyDbContext dbContext) { _dbContext = dbContext; } // 控制器的Action方法... protected override void Dispose(bool disposing) { if (disposing) { // 清理托管资源,比如数据库上下文 _dbContext.Dispose(); } base.Dispose(disposing); } }
完成以上修改后,请求结束时框架会调用ReleaseController,触发控制器的Dispose逻辑,GC就能正常回收控制器实例,解决内存持续增长的问题。
内容的提问来源于stack exchange,提问作者user2577528
相关产品推荐
相关产品推荐

