让我们看这段代码:
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
}
关于c# - Lambda表达式,多线程中的外部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7723059/