3

I am using a class that manages a pool of threads to run actions. Originally it was coded to take an Action (with no parameter) and I was calling it like this:

void LoadTasks()
{
   string param;

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

As the threads ran some were fine, but occasionally the param variable was not what I expected ... it was a "newer" value and not what I intended to send to the method.

Changing the thread pool to accept Action<Object> and calling without a lambda -- like this threadPool.EnqueueTask(SomeMethod, param) -- worked around my problem.

I see quite a few questions about C# lambdas about thread-safety. For example, an accepted answer of lambdas are much less likely to be thread safe than you would expect. I'm finding other questions and answers about lambdas/closures/scoping to be confusing. So I am looking for an explanation of lambdas and variable scope, ideally relating to the problem in my example.

4

1 回答 1

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 都关闭了它自己的变量,而不是让它们都关闭同一个变量。

于 2013-07-10T15:29:59.380 回答