c# - Lambda表达式,多线程中的外部变量

标签 c# multithreading 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 传播到所有事件?

最佳答案

变量捕获发生在 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/

相关文章:

c# - Entity Framework 、批量插入和维护关系

C++ 线程安全括号运算符代理

asp.net - 每个请求 asp.net 单线程

c++ - Constexpr 变量在 Lambda 内部显示为未初始化

.net - 在表达式中包含方法类

C# 反射 : providing T for a generic method

c# - 用于从字符串中删除除第一个和最后一个字符之外的元音的正则表达式

java - 不理解 'volatile' 关键字

c++ - std::function 的目的是什么以及如何使用它?

c# - 对于 nunit 测试夹具,多个类别是否会导致多个测试?