6

我正在使用EntityFramework並在一堆後臺作業類中實現通用存儲庫和工作單元模式。作業類是使用Unity DI創建的,因此它們可以注入依賴項,這些依賴項主要是存儲庫和UnitOfWork對象。 知識庫和工作單元應共享EF DbContextUnity PerThreadLifetimeManager和任務

一個共同的工作應該是這樣的:

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

而且我已經註冊的單位的工作和存儲庫Unity使用PerThreadLifetimeManager,認爲這將允許在一個任務的上下文(以及那個工作對象)內共享已註冊的實例,但不在外部。

我遇到的問題是有時候作業會被注入處理對象,這顯然不是很好。我一直在閱讀,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(); 
}); 

回答

6

你得到處置的對象,因爲並行庫使用一個線程池,並統一返回相同的對象池的同一個線程。

如果您以您發佈的方式使用容器,我建議您使用PerResolveLifetimeManager。這樣,當你解析一個對象時,整個分辨率圖共享相同的實例,但實例對於每個分辨率是唯一的:當它調用Resolve時,每個任務都有它自己的實例。

+1

你的回答是正確的,但我只是想補充說,我最終使用了'HieararchicalLiftetimeManager'並在任務中創建了一個子容器。這是因爲我需要使用容器來動態解析其中一個作業類的一些服務。我知道使用容器作爲服務定位器是一種代碼味道,但這就是它的設置,現在沒有時間去修復它... – Pinetree

+1

@Pinetree任何機會,你可以展示你如何做到這一點?謝謝 – nfplee

+0

@nfplee我在家裏沒有代碼,我不記得它在我的頭頂。我將在星期一上班時發佈我所做的事情。 – Pinetree