multithreading和lambda变量范围

我正在使用一个管理线程池来运行操作的类。 最初它被编码为采取Action(没有参数),我这样称呼它:

void LoadTasks() { string param; // some code loops and changes param { threadPool.EnqueueTask(() => SomeMethod(param)); } } 

由于线程运行一些很好,但偶尔param变量不是我所期望的…它是一个“更新”的值,而不是我打算发送给该方法。

更改线程池以接受Action并在没有lambda的情况下调用 – 就像这个threadPool.EnqueueTask(SomeMethod, param) – 解决了我的问题。

关于线程安全,我看到了很多关于C#lambdas的问题。 例如,lambdas 的公认答案 比您预期的更不可能是线程安全的。 我发现关于lambdas / closures / scoping的其他问题和答案令人困惑。 所以我正在寻找lambdas和变量范围的解释,理想情况与我的例子中的问题有关。

所以问题是你要关闭你不想要的变量。 在大多数情况下,最简单的方法是创建一个新的局部变量,复制你曾经关闭的变量,然后关闭

所以代替:

 for(int i = 0; i < number; i++) { threadPool.EnqueueTask(() => SomeMethod(someList[i])); } 

你可以这样做:

 for(int i = 0; i < number; i++) { int copy = i; threadPool.EnqueueTask(() => SomeMethod(someList[copy])); } 

现在每个lambda都关闭它自己的变量,而不是让所有lambda都接近同一个变量。