让我们看下面的代码:
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会传播到所有事件?
最佳答案
变量捕获根据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
}