2011-10-11 31 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参考将指向范围的值。