多线程和lambda变量范围

时间:2013-07-10 15:21:06

标签: c# multithreading lambda scope closures

我正在使用一个管理线程池来运行操作的类。最初它被编码为采取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和变量范围的解释,理想情况与我的例子中的问题有关。

1 个答案:

答案 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都关闭同一个变量。