gpt4 book ai didi

c# - 将 Windsor CaSTLe 注入(inject)的依赖项传递给并行线程 - Dispose() 问题

转载 作者:太空狗 更新时间:2023-10-29 23:26:26 27 4
gpt4 key购买 nike

我使用带有 CaSTLe Windsor 的 ASP.NET MVC 作为我的 IoC 容器,组件生活方式设置为 PerWebRequest。我的存储库(这是注入(inject)的依赖项)在构造函数中创建了 Entity Framework 的 ObjectContext 实例,并将其存储在私有(private)实例变量中。我的存储库实现了 IDisposable,在我的 Dispose 方法中,我处理了 ObjectContext。我认为所有这些都是非常标准的,这里有一个简化的例子:

存储库:

 public class Repository : IRepository {

private MyContext _dc; // MyContext inherits from ObjectContext

public Repository() {
_dc = new MyContext();
}

public void Dispose() {;
_dc.Dispose();
}
}

为确保没有内存泄漏并调用我的 Repository 的 Dispose(),我覆盖了 DefaultControllerFactory 的 ReleaseController 方法以释放 Windsor 的容器:

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);
}
}

我认为所有这些都非常标准。但是,我想分离出一个并行线程,并在该并行线程内利用 IRepository 依赖项。我的问题是我的存储库在我使用它时已经被处理掉了:

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");
}
}

其他人是怎么解决这个问题的?如何将依赖项传递给并行线程?

提前致谢。

最佳答案

创建一个新的 Repository 实例。 ObjectContext 的构建成本低廉。

或者,您可以将处置存储库的责任附加到长时间运行的线程。我搞砸了,我认为对您的代码进行这些更改将解决您的问题:

在你的 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);
}

在家庭 Controller 中

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");
}
}

和新的基地 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;
}

关于c# - 将 Windsor CaSTLe 注入(inject)的依赖项传递给并行线程 - Dispose() 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5366706/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com