Passing a Windsor Castle dependent on a parallel task - Dispose ()

I am using ASP.NET MVC with Castle Windsor as my IoC container with the lifestyle component installed in PerWebRequest. My repository (which is dependent on it) creates an instance of the Entity Framework ObjectContext in the constructor, and I store it in a private instance variable. My repository implements IDisposable and inside my Dispose method, I delete the ObjectContext. I think all this is pretty standard, and here's a simplified illustration:

Repository:

public class Repository : IRepository { private MyContext _dc; // MyContext inherits from ObjectContext public Repository() { _dc = new MyContext(); } public void Dispose() {; _dc.Dispose(); } } 

To make sure there is no memory leak and that my Dispose () repository is being called, I override the DefaultControllerFactory ReleaseController method to free the Windsor container:

 public class WindsorControllerFactory : DefaultControllerFactory { IWindsorContainer _container; public WindsorControllerFactory(IWindsorContainer container) { _container = container; // Do stuff to register all controller types } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { // Do stuff to resolve dependency } public override void ReleaseController(IController controller) { // by releasing the container, Windsor will call my Dispose() method on my repository _container.Release(controller); base.ReleaseController(controller); } } 

I think all this is pretty standard. However, I would like to unscrew the parallel stream, and the IRepository dependency is used inside this parallel stream. My problem is that my repository will already be deleted by the time it is used:

 public class HomeController : Controller { IRepository _repository; public HomeController(IRepository repository) { _repository = repository; } public ActionResult Index() { var c = _repository.GetCompany(34); new Task(() => { System.Threading.Thread.Sleep(2000); // simulate long running task // will throw an error because my repository (and therefore, ObjectContext) will have been disposed. var c2 = _repository.GetCompany(35); }).Start(); return Content(c.Name, "text/plain"); } } 

How do other people solve this problem? How do you pass your dependencies to a parallel thread?

Thanks in advance.

+4
source share
1 answer

Create a new repository instance. ObjectContexts are inexpensive to build.

OR, you can take responsibility for removing the repository for a long stream. I messed it up, I think these changes in the code will help solve your problem:

In your WindsorControllerFactory

  protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { IController controller; // Do stuff to resolve dependency if(controller is LongTaskController) { ((LongTaskController) controller).CompleteLongTask += (sender, args) => _container.Release(controller); } } public override void ReleaseController(IController controller) { // by releasing the container, Windsor will call my Dispose() method on my repository if(!(controller is LongTaskController && ((LongTaskController)controller).HasLongTask) { _container.Release(controller); } base.ReleaseController(controller); } 

In HomeController

 public class HomeController : LongTaskController { private readonly IRepository _repository; public HomeController(IRepository repository) { _repository = repository; } public ActionResult Index() { var c = _repository.GetCompany(34); DoLongTask(() => { Thread.Sleep(200); var c2 = _repository.GetCompany(35); }); return Content(c.Name, "text/plain"); } } 

And the new base controller

 public abstract class LongTaskController: Controller,IHasLongTask { private bool _hasLongTask; public bool HasLongTask { get { return _hasLongTask; } } public event EventHandler CompleteLongTask; void IHasLongTask.DoLongTask(Action action) { DoLongTask(action); } protected void DoLongTask(Action action) { _hasLongTask = true; if (CompleteLongTask == null) { throw new NullReferenceException("Controller.CompleteLongTask cannot be null when Controller does a long running task."); action += () => CompleteLongTask(this, EventArgs.Empty); } new Task(action).Start(); } } public interface IHasLongTask { bool HasLongTask { get; } void DoLongTask(Action action); event EventHandler CompleteLongTask; } 
+4
source

Source: https://habr.com/ru/post/1344422/


All Articles