让我们看下面的代码:

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
}

09-28 01:40