5

Tôi sử dụng Simple Injector làm thùng chứa IoC của mình. SimpleInjector sử dụng this simple technique to handle mixed life style for Per Thread and Per Web RequestSử dụng các phụ thuộc trên nhiều luồng với Parallel.ForEach

container.RegisterPerWebRequest<IWebRepository, Repository>(); 
container.RegisterLifetimeScope<IThreadRepository, Repository>(); 
container.Register<IRepository>(container.GetInstance<Repository>()); 

// Register as hybrid PerWebRequest/PerLifetimeScope. 
container.Register<Repository>(() => 
{ 
    Repository repository; 
    if (HttpContext.Current != null) 
     repository = (Repository)container.GetInstance<IWebRepository>(); 
    else 
     repository = (Repository)container.GetInstance<IThreadRepository>(); 

    return repository; 
}); 

Thật không may (và rõ ràng!), Ở đâu đó trong lớp UnitOfWork tôi này đem lại cho tôi một vấn đề khi tôi sử dụng Parallel.ForEach và cố gắng gọi vào nhiều trường hợp của các lớp Repository song song như chỉ đầu tiên của chủ đề tìm thấy một giá trị trong HttpContext.Current

using (TransactionScope scope = new TransactionScope()) 
{ 
    Parallel.ForEach(new List<IRepository>() { _repository1, _repository2 ... }, 
     (repository) => 
     { 
      repository.Commit(); 
     }); 
    scope.Complete(); 
} 

Bây giờ mà tôi đã viết xong ra các câu hỏi tôi có thể thấy tôi có thể yêu cầu những điều không thể hoặc một cái gì đó ngu ngốc ... nhưng cái quái gì. .. điều này có thể được thực hiện? Có thể đăng ký một yêu cầu/chủ đề có sẵn cho nhiều chủ đề nội bộ không?

Trả lời

7

Với tiêm phụ thuộc, bạn cố gắng tập trung kiến ​​thức về tuổi thọ của đối tượng. Nơi tập trung này được gọi là Composition Root. Khi bạn bắt đầu truyền các phụ thuộc từ một luồng này sang luồng khác, các phần đó của mã phải biết liệu có an toàn để vượt qua các phụ thuộc đó hay không. Ví dụ, là những phụ thuộc thread-an toàn? Những phụ thuộc đó có thể chạy trong ngữ cảnh mới đó (ngoài yêu cầu HTTP hoặc WCF) không? Điều này có thể không quan trọng để phân tích trong nhiều tình huống, nhưng ngăn cản bạn thay đổi những phụ thuộc với các triển khai khác, vì bây giờ bạn phải nhớ rằng có một vị trí trong mã của bạn nơi điều này đang xảy ra và bạn cần biết phụ thuộc nào được truyền vào. Bạn phân cấp lại kiến ​​thức này, làm cho việc xác định cấu hình DI của bạn trở nên khó khăn hơn và làm cho việc định cấu hình container dễ dàng hơn theo cách làm cho mã của bạn không trực tiếp (tốt nhất) hoặc gây khó khăn trong việc gỡ lỗi các điều kiện của cuộc đua).

Do đó, an toàn nhất là để cho mỗi chủ đề mới bắt đầu xây dựng biểu đồ đối tượng mới bằng cách yêu cầu vùng chứa cho nó. Không truyền các phụ thuộc (điều đó có nghĩa là: các cá thể được quản lý và tiêm bởi container) từ một luồng này sang luồng khác.

Trong trường hợp của bạn, bạn thậm chí có vẻ gặp sự cố vì kho lưu trữ của bạn dường như có mối quan hệ với ngữ cảnh http vì chúng dường như không truyền được cho các chủ đề khác. Trong trường hợp đó, điều này khá dễ dàng: đừng làm điều này ;-)

Điều này không có nghĩa là bạn không thể thực hiện đa luồng để tăng tốc hiệu suất theo bất kỳ cách nào. Tuy nhiên, bạn phải đảm bảo rằng thao tác này không di chuyển các phụ thuộc từ một luồng vào luồng, hoặc khi chúng thực hiện; hãy đảm bảo rằng mã này (trong trường hợp của bạn là Parallel.ForEach) nằm bên trong Root Root của ứng dụng của bạn, vì đây là nơi duy nhất có thể/nên biết liệu hoạt động này có an toàn để thực hiện hay không.

Tuy nhiên, trong trường hợp cụ thể của bạn, tôi thấy nó khá đáng sợ khi bạn thực hiện nhiều chuỗi. Không nên cam kết của đơn vị công việc đó là nguyên tử? Bạn có chắc chắn rằng cam kết này vẫn còn nguyên tử khi bạn thực hiện các cam kết kho lưu trữ trên các chủ đề khác nhau? Điều gì sẽ xảy ra khi một trong những cam kết thất bại nhưng những người khác lại thành công? Làm thế nào để bạn rollback các hoạt động đã thành công? Tôi nghĩ rằng bạn có thể (và bạn có thể đã có) giải quyết những vấn đề này, nhưng giải pháp như vậy cho biết thêm rất nhiều phức tạp thêm cho hệ thống. Bạn phải nghiêm túc tự hỏi liệu cải thiện hiệu suất có thực sự bù đắp với độ phức tạp thêm mà bạn đã thêm vào hệ thống hay không.

Bạn có thể tìm thêm thông tin về cách làm việc với tiêm phụ thuộc trong các ứng dụng đa luồng here.

Các vấn đề liên quan