6

Tôi đang sử dụng EntityFramework và triển khai một kho lưu trữ chung và mẫu đơn vị công việc trong một loạt các lớp công việc nền. Các lớp công việc được tạo ra bằng cách sử dụng Unity DI để chúng có thể được tiêm với các phụ thuộc, mà chủ yếu là các kho và đối tượng UnitOfWork. Kho lưu trữ và đơn vị công việc phải chia sẻ EF DbContext.Unity PerThreadLifetimeManager and Tasks

Một công việc chung sẽ trông như thế này:

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

Tất cả các công việc đang chạy trong nhiệm vụ mới, một cái gì đó như thế này

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

Và tôi đã đăng ký đơn vị-of-nơi làm việc và kho với Unity sử dụng PerThreadLifetimeManager, nghĩ rằng điều đó sẽ cho phép chia sẻ các cá thể đã đăng ký trong ngữ cảnh của một nhiệm vụ (và trong một đối tượng công việc đó), nhưng không phải ở bên ngoài.

Sự cố mà tôi gặp phải là đôi khi công việc sẽ được tiêm các đối tượng được xử lý, điều này rõ ràng là không tốt lắm. Tôi đã đọc rằng Task.Factory.StartNew() không phải lúc nào cũng sử dụng một chủ đề mới. Điều này có nghĩa là PerThreadLifetimeManager sẽ chia sẻ các đối tượng giữa các tác vụ? Nếu điều này là đúng, có cách nào khác để quản lý thời gian chờ của đối tượng với sự thống nhất, điều này sẽ cho phép mỗi tác vụ làm việc trong sự cô lập, bất kể chuỗi nó đang chạy chưa?

EDIT:

Trong khi câu trả lời được lựa chọn dưới đây sẽ đạt được điều tương tự, tôi đã kết thúc bằng cách sử dụng HierarchicalLifetimeManager và con container để đạt được cách ly phụ thuộc cho từng công việc.

Dưới đây là một ví dụ:

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

Trả lời

6

Bạn nhận được đối tượng thanh lý khoản vì thư viện song song sử dụng một hồ bơi thread và Unity trả về đối tượng tương tự cho các chủ đề tương tự của hồ bơi.

Nếu bạn sử dụng vùng chứa theo cách bạn đã đăng, tôi khuyên bạn nên sử dụng PerResolveLifetimeManager. Bằng cách này, khi bạn giải quyết một đối tượng, toàn bộ đồ thị độ phân giải chia sẻ cùng một cá thể nhưng cá thể là duy nhất cho mỗi độ phân giải: mỗi tác vụ sẽ có cá thể riêng khi nó gọi Resolve.

+1

Câu trả lời của bạn là chính xác, nhưng tôi chỉ muốn thêm rằng tôi đã kết thúc bằng cách sử dụng một 'HieararchicalLiftetimeManager' và tạo một thùng chứa con trong nhiệm vụ. Điều này là do tôi cần sử dụng vùng chứa để giải quyết động một số dịch vụ từ một trong các lớp công việc. Tôi biết sử dụng một container như một định vị dịch vụ là một mùi mã, nhưng đó là cách nó được thiết lập, và không có thời gian để sửa nó ... – Pinetree

+1

@Pinetree Bất kỳ cơ hội nào bạn có thể chỉ ra cách bạn đã làm điều này? Cảm ơn – nfplee

+0

@nfplee Tôi không có mã ở nhà và tôi không nhớ nó ở trên đầu của tôi. Tôi sẽ đăng những gì tôi đã làm vào thứ hai khi tôi đi làm. – Pinetree