2011-10-11 24 views
6

Cho phép lấy mã này:biểu Lambda, các biến bên ngoài trong multithread

public void Hit(int npage) 
     { 
      bool fetch = false; 
      lock (pagesHit) 
      { 
       if (!pagesHit.Contains(npage)) 
       { 
        pagesHit.Add(npage); 
        fetch = true; 
       } 
      } 
      if (fetch) 
      { 
       pageFiller.Completed += (s, e) => 
        { 
         lock (pagesHit) 
         { 
          pagesHit.Remove(npage); 
         } 
        }; 
      } 

     } 

chức năng này có thể được gọi từ các chủ đề khác nhau. Mục tiêu rõ ràng là tránh tìm nạp một trang đã được lập lịch để tìm nạp. Đối tượng filler cho thấy một sự kiện được đăng ký thông qua một biểu thức lambda. Câu hỏi của tôi là: chúng ta có thể nói rằng tham số npage được xử lý chính xác trong kịch bản đa luồng không? tốt hơn: mỗi đăng ký sự kiện nhận được thông số npage riêng của mình hoặc lần xem npage mới nhất được truyền cho tất cả các sự kiện?

Trả lời

7

Ghi lại biến xảy ra theo phạm vi khai báo của npage. Tham số npage được khai báo ở cấp phương thức và không thay đổi trong phương thức đó - do đó, việc sử dụng npagehoàn toàn an toàn chỉ.

Vấn đề bạn đang tránh sẽ xảy ra nếu bạn đang thay đổi một biến trong phạm vi tuyên bố của mình, điển hình là một vòng lặp - tức là

for(int npage = 0; npage < 100 ; npage++) 
    Foo((s,e) => DoSomething(npage)); // not safe; npage shared between all 

Tuy nhiên, bằng cách phá vỡ nó thành một phương pháp bạn tránh điều này, tức là

for(int i = 0; i < 100; i++) 
    Hit(i); 
... 
void Hit(int npage) { 
    Foo((s,e) => DoSomething(npage)); // safe; npage is per-call 
} 
2

Mỗi lần gọi phương thức Hit sẽ có các giá trị khác nhau cho tham chiếu npage.

Nói cách khác, mỗi chuỗi gọi phương thức này sẽ có riêng npage.

Đó là bởi vì, đối với mỗi chuỗi gọi phương thức này, hoạt động và đăng ký trình xử lý sự kiện sẽ diễn ra ở các phạm vi khác nhau, vì vậy, tham chiếu npage sẽ trỏ đến giá trị của phạm vi.

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