我正在使用一个管理线程池来运行操作的类。最初它被编码为采取Action(没有参数),我这样称呼它:
void LoadTasks()
{
string param;
// some code loops and changes param
{
threadPool.EnqueueTask(() => SomeMethod(param));
}
}
由于线程运行一些很好,但偶尔param变量不是我预期的......它是一个“更新”的值,而不是我打算发送给方法。
更改线程池以接受Action<Object>
并在没有lambda的情况下调用 - 就像这个threadPool.EnqueueTask(SomeMethod, param)
- 解决了我的问题。
我看到很多关于C#lambdas关于线程安全的问题。例如,an accepted answer lambda 比线程安全的可能性要小得多。我发现有关lambdas / closures / scoping的其他问题和答案令人困惑。所以我正在寻找lambda和变量范围的解释,理想情况与我的例子中的问题有关。
答案 0 :(得分:2)
所以问题是你要关闭你不想要的变量。在大多数情况下,最简单的方法是创建一个新的局部变量,复制你曾经关闭的变量,然后关闭那个。
所以而不是:
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都关闭同一个变量。