Unity PerThreadLifetimeManager and tasks

I use EntityFramework and embed a common repository and work template into a bunch of background work classes. Job classes are created using Unity DI so that dependencies can be introduced to them, which are mainly repositories and a UnitOfWork object. Storage and unit of work must share the EF DbContext .

The general task will look as follows:

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

All tasks start in new tasks, something like this

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

And I registered the unit of work and repositories with Unity using PerThreadLifetimeManager , believing that this will allow the exchange of registered instances in the context of one task (and in this one task object), but not outside.

The problem I am facing is that sometimes tasks will be entered with located objects, which is obviously not very good. I read that Task.Factory.StartNew() does not always use the new thread. Does this mean that PerThreadLifetimeManager will share objects between tasks? If so, is there another way to control the elevator of an object with a unit that will allow each task to work in isolation, regardless of which thread is running?

EDIT:

While the selected answer below will achieve the same, I ended up using the HierarchicalLifetimeManager and child containers to ensure dependency isolation for each job.

Here is an example:

 // 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(); }); 
+6
source share
1 answer

You get objects because the parallel library uses a thread pool, and Unity returns the same object for a single thread in the pool.

If you use the container in the form in which you placed it, I suggest you use the PerResolveLifetimeManager . Thus, when you resolve an object, the entire resolution graph has the same instance, but the instance is unique for each resolution: each task will have its own instance when Resolve called.

+6
source

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


All Articles