2011-10-11 78 views
6

外變量讓我們這樣的代碼:Lambda表達式,在多線程

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

     } 

此函數可以從不同的線程中調用。目標顯然是爲了避免獲取已經計劃獲取的頁面。填充對象公開通過lambda表達式訂閱的事件。我的問題是:我們可以說多參數場景中的參數npage正確處理嗎?更好:每個事件訂閱收到它自己的npage參數,或最後npage看到傳播到所有事件?

回答

7

變量捕獲發生在聲明範圍npage。參數npage在方法級別聲明,並且在該方法內不會更改 - 因此確實使用npage完全是線程安全。

你避免如果你改變變量的聲明範圍內,通常是循環將出現問題 - 即

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

然而,通過分解成一個方法,你避免這種情況,即

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

每個Hit方法調用將具有不同的值npage參考。

換句話說,調用這個方法的每個線程都有自己的npage

這是因爲,對於每個線程調用此方法,它的操作和事件處理程序訂閱將在不同的範圍,因此,NPAGE參考將指向範圍的值。