2009-03-05 31 views
6

Tôi sẽ đăng câu hỏi nhưng đã tìm ra câu hỏi trước và quyết định đăng câu hỏi và câu trả lời - hoặc ít nhất là các quan sát của tôi.Sử dụng các đại biểu vô danh với .NET ThreadPool.QueueUserWorkItem

Khi sử dụng một đại biểu ẩn danh làm WaitCallback, trong đó ThreadPool.QueueUserWorkItem được gọi trong vòng lặp foreach, có vẻ như cùng một giá trị foreach được chuyển vào mỗi chuỗi.

List<Thing> things = MyDb.GetTheThings(); 
foreach(Thing t in Things) 
{ 
    localLogger.DebugFormat("About to queue thing [{0}].", t.Id); 
    ThreadPool.QueueUserWorkItem(
     delegate() 
     { 
      try 
      { 
       WorkWithOneThing(t); 
      } 
      finally 
      { 
       Cleanup(); 
       localLogger.DebugFormat("Thing [{0}] has been queued and run by the delegate.", t.Id); 
      } 
     } 
} 

Đối với một bộ sưu tập gồm 16 thứ trong Điều tôi quan sát thấy mỗi mục 'Thing' được chuyển đến WorkWithOneThing tương ứng với mục cuối cùng trong danh sách 'sự vật'.

Tôi nghi ngờ điều này là do đại biểu đang truy cập biến bên ngoài 't'. Lưu ý rằng tôi cũng đã thử nghiệm với việc chuyển Thing như một tham số cho đại biểu ẩn danh, nhưng hành vi vẫn không chính xác.

Khi tôi xác thực lại mã để sử dụng phương thức WaitCallback được đặt tên và chuyển Thing 't' sang phương thức, viola ... thể hiện thứ i của thứ được truyền chính xác vào WorkWithOneThing.

Bài học song song tôi đoán. Tôi cũng tưởng tượng rằng gia đình Parallel.For đề cập đến điều này, nhưng thư viện đó không phải là một lựa chọn cho chúng tôi vào thời điểm này.

Hy vọng điều này sẽ giúp người khác tiết kiệm thời gian.

Howard Hoffman

+0

Nếu bạn cố gắng để biên dịch mã này, sẽ không nhận được một lỗi "System.Threading.WaitCallback' không mất 'đối số 0'" như bạn chỉ định không param – ram

+0

Ram - Hãy thử thay đổi việc kê khai trên từ: đại biểu() { ... } để đại biểu { ... } Đó là những gì tôi đã có tạm biệt thay đổi. Hy vọng điều này sẽ giúp bạn. –

Trả lời

7

Điều này đúng và mô tả cách C# nắm bắt các biến bên ngoài bên trong bao đóng. Nó không trực tiếp là một vấn đề về song song, mà là về các phương thức nặc danh và các biểu thức lambda.

This question thảo luận chi tiết về tính năng ngôn ngữ này và ý nghĩa của nó.

+0

Bài viết này cũng hữu ích: http://www.managed-world.com/archive/2008/06/13/lambdas---know-your-closures.aspx –

1

Đây là sự cố thường gặp khi sử dụng các bao đóng và đặc biệt rõ ràng khi xây dựng các truy vấn LINQ. Do đó, việc đóng tham chiếu biến, chứ không phải nội dung của nó, để làm cho ví dụ của bạn hoạt động, bạn chỉ có thể chỉ định một biến bên trong vòng lặp nhận giá trị của t và sau đó tham chiếu trong kết thúc. Điều này sẽ đảm bảo mỗi phiên bản của đại biểu ẩn danh của bạn tham chiếu đến một biến khác.

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