10

Tôi muốn lưu trữ thông tin ngữ cảnh ghi nhật ký trong TLS để tôi có thể đặt giá trị tại điểm nhập và có giá trị đó trong tất cả các ngăn xếp kết quả. Điều này làm việc tốt, nhưng tôi cũng sử dụng TPL và ThreadPool. Vấn đề sau đó sẽ trở thành cách di chuyển dữ liệu TLS đến các chủ đề khác. Tôi có thể làm tất cả bản thân mình, nhưng sau đó tôi mất phương pháp tốt đẹp như Parallel.For.Làm thế nào để quản lý lưu trữ cục bộ luồng (TLS) khi sử dụng TPL?

Có cách nào để sao chép TLS khi sử dụng TPL không? Điều này cũng sẽ áp dụng cho C# khi nó có tính năng chờ.

Cảm ơn, Erick

Trả lời

5

Thông thường, điều này được thực hiện thông qua việc sử dụng một quá tải của Parallel.For rằng đã cung cấp cho các dữ liệu chủ đề của địa phương.

Quá tải này cho phép bạn cung cấp khởi tạo và đại biểu cuối cùng, có hiệu quả trở thành khởi tạo cho mỗi luồng cho dữ liệu cục bộ luồng của bạn và chức năng giảm ở cuối để "hợp nhất" kết quả với nhau (được chạy một lần cho mỗi thread). I wrote about this in detail here.

Các hình thức cơ bản là để làm một cái gì đó như:

object sync = new object(); 
double result = 0; 

Parallel.For(0, collection.Count, 
    // Initialize thread local data: 
    () => new MyThreadSpecificData(), 
    // Process each item 
    (i, pls, currentThreadLocalData) => 
    { 
     // Generate a NEW version of your local state data 
     MyThreadSpecificData newResults = ProcessItem(collection, i, currentThreadLocalData); 
     return newResults; 
    }, 
    // Aggregate results 
    threadLocalData => 
    { 
     // This requires synchronization, as it happens once per thread, 
     // but potentially simultaneously 
     lock(sync) 
      result += threadLocalData.Results; 
    }); 
+0

Cảm ơn Reed - điều này làm những gì tôi muốn, tuy nhiên tôi đã tìm thấy một cách khác để giải quyết vấn đề. Tuy nhiên, đây là thứ tuyệt vời mà tôi sẽ sớm sử dụng. –

+0

Tôi tự hỏi tại sao họ lại bao gồm quá tải xấu xí như vậy? Ở tốc độ đó, nó sẽ sạch hơn chỉ để khởi tạo dữ liệu luồng-địa phương và khởi tạo nó trong ủy nhiệm chính của bạn. Trừ khi họ đã tối ưu hóa nó như thế nào ..? –

+0

@ TimLovell-Smith Dữ liệu cục bộ luồng được sử dụng lại trên nhiều cuộc gọi đại biểu, do đó, nó không thể được khởi tạo/hoàn thành trong một đại biểu duy nhất. (Đó là điểm;)) –

4

tôi tìm thấy một giải pháp cho vấn đề mà không yêu cầu mã. Tôi đã có thể sử dụng CallContext để đính kèm dữ liệu vào một "chuỗi logic". Dữ liệu này được chuyển từ chuỗi bắt đầu đến các luồng được tạo bởi TPL cũng như ThreadPool.

http://www.wintellect.com/CS/blogs/jeffreyr/archive/2010/09/27/logical-call-context-flowing-data-across-threads-appdomains-and-processes.aspx

+5

Chỉ cần FYI - Cơ chế này là nhiều, chậm hơn nhiều so với việc sử dụng TLS, vì nó tuần tự hóa dữ liệu thông qua mỗi lệnh gọi ... –

0

Có, tất nhiên, nhưng thay thế khác: Viết một lớp TaskLocal (T), như chúng ta đã làm, mà căn cứ lưu trữ trên Task hiện tại, chứ không phải là chủ đề hiện hành. Thành thật mà nói, tôi không có ý tưởng tại sao Microsoft đã không làm điều này như là một phần của việc thực hiện Nhiệm vụ ban đầu của họ.

Lưu ý thực hiện quan trọng: Vì mã tác vụ chờ cuộc gọi có thể được chia nhỏ và tiếp tục là khác nhau TaskId, bạn cũng cần làm những gì chúng tôi đã làm và triển khai phương pháp trong TaskLocal (T) cho những người trước đó, sau đó lưu TaskId ban đầu ở đầu Nhiệm vụ và ánh xạ nó sau mỗi cuộc gọi đang chờ.

+0

Một mẫu mã chứng minh điều này sẽ nhận được +1 từ tôi :-) – JoshBerke

+0

Tôi sẽ xem những gì tôi có thể làm ... (: – Thought

+0

Điều đó sẽ tuyệt vời! – JoshBerke

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