多线程和lambda变量范围

本文关键字:范围 变量 lambda 多线程 | 更新日期: 2023-09-27 18:21:55

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

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

随着线程的运行,有些线程很好,但偶尔param变量不是我所期望的。。。这是一个"更新"的值,而不是我想要发送给该方法的值。

将线程池更改为接受Action<Object>并在没有lambda的情况下调用(如threadPool.EnqueueTask(SomeMethod, param))解决了我的问题。

我看到了很多关于C#lambdas的关于线程安全的问题。例如,lambdas的公认答案不太可能是线程安全的我发现关于lambdas/闭包/范围界定的其他问题和答案令人困惑。因此,我正在寻找lambdas和可变范围的解释,最好与我的例子中的问题相关。

多线程和lambda变量范围

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

所以不是:

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都闭合在同一个变量上。