【问题标题】:Unity PerThreadLifetimeManager and TasksUnity PerThreadLifetimeManager 和任务
【发布时间】:2013-11-07 20:51:44
【问题描述】:

我正在使用EntityFramework 并在一堆后台作业类中实现通用存储库和工作单元模式。作业类是使用 Unity DI 创建的,因此它们可以注入依赖项,这些依赖项主要是存储库和 UnitOfWork 对象。 存储库和工作单元应共享 EF DbContext

一个普通的工作应该是这样的:

public class CommonJob : IJob, IDisposable
{        
    private IRepo<SomeEntity> _repo;
    private IUnitOfWork _uow;

    public CommonJob(IRepo<SomeEntity> repo, IUnitOfWork uow)
    {
        _repo = repo;
        _uow = uow;
    }

    public void RunJob()
    {
        // do stuff here
    }

    public void Dispose()
    {
        _uow.Commit();
        _uow.Dispose();
    }
}

所有作业都在新任务中运行,类似这样

Task.Factory.StartNew(() => {
    // container is UnityContainer
    var job = container.Resolve<CommonJob>();
    job.RunJob();
    job.Dispose();
});

我已经使用 PerThreadLifetimeManager 在 Unity 中注册了工作单元和存储库,我认为这将允许在一项任务的上下文中(以及在该作业对象中)共享注册的实例,但不是外面。

我遇到的问题是,有时作业会被注入已处置的对象,这显然不是很好。我一直在阅读 Task.Factory.StartNew() 并不总是使用新线程。这是否意味着PerThreadLifetimeManager 将在任务之间共享对象?如果这是真的,是否有另一种统一管理对象提升时间的方法,这将允许每个任务独立工作,而不管它运行在哪个线程上?

编辑:

虽然下面选择的答案将实现相同的效果,但我最终使用 HierarchicalLifetimeManager 和子容器来实现每个作业的依赖隔离。

这是一个例子:

// registering the dependencies, 
// these should be singletons, but only within the context of one job
_container.Register(typeof(IRepo<>), typeof(Repo<>), new HierarchicalLifetimeManager())
          .Register<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());

// starting a new job
Task.Factory.StartNew<IUnityContainer>(() => 
{
    // create a child container to remove instance sharing between tasks
    var childContainer = _container.CreateChildContainer();

    // figure out and resolve the job class from the child container
    // this will make sure that different jobs do not share instances
    var jobType = GetJobType();
    var job = childContainer.Resolve(jobType) as IJob;

    job.RunJob();

    return childContainer;
}).ContinueWith(previousTask => {
    // when the job is done, dispose of the child container
    task.Result.Dispose(); 
});

【问题讨论】:

    标签: c# .net-4.0 dependency-injection task-parallel-library unity-container


    【解决方案1】:

    因为并行库使用线程池,您会得到已处置的对象,而 Unity 会为池中的同一线程返回相同的对象。

    如果你按照你发帖的方式使用容器,我建议你使用PerResolveLifetimeManager。这样,当您解析一个对象时,整个分辨率图共享同一个实例,但每个分辨率的实例都是唯一的:每个任务在调用Resolve 时都会有自己的实例。

    【讨论】:

    • 您的答案是正确的,但我只想补充一点,我最终使用了HieararchicalLiftetimeManager 并在任务中创建了一个子容器。这是因为我需要使用容器从其中一个作业类中动态解析一些服务。我知道使用容器作为服务定位器是一种代码味道,但这就是它的设置方式,现在没有时间修复它......
    • @nfplee 我家里没有代码,我不记得它了。我会在周一上班时发布我所做的事情。
    • @nfplee 我一直很忙,所以花了我一段时间,但我终于使用HieararchicalLiftetimeManager 编辑了问题以包含我的解决方案
    猜你喜欢
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 2019-09-29
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    相关资源
    最近更新 更多