Unity PerThreadLifetimeManager和任务

时间:2013-08-19 07:52:17

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

我正在使用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(); 
});

1 个答案:

答案 0 :(得分:6)

由于并行库使用线程池,因此您将获得处置对象,Unity会为池的同一线程返回相同的对象。

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