我正在以这种方式定义一个参差不齐的线程数组(这样每个线程可以在它自己的目录树上运行)
Task[][] threads = new Task[InstancesDir.Length][];
for (int i = 0; i < InstancesDir.Length; i++)
{
threads[i] = new Task[InstancesDir[i].Length];
}
for (int i = 0; i < FilesDir.Length; i++)
{
for (int j = 0; j < FilesDir[i].Length; j++)
{
threads[i][j] = Task.Run(() =>
{
Calculate(i, j, InstancesDir, FilesDir, PointSum);
});
}
Task.WaitAll(threads[i]);
}
但是在计算中,我总是得到j的值&gt; = FilesDir [i] .Length。我还检查了除数组之外的值传递的对象。什么可能是一个解决方法,这可能是这种行为的原因?
PS。引入共享锁可能有助于缓解并发问题,但我想知道这种行为的原因。
答案 0 :(得分:3)
但是在计算中我总是得到j的值&gt; = FilesDir [i] .Length
这不是并发问题,因为您的for
循环正在单个线程上执行。发生这种情况是因为lambda表达式正在关闭i
和j
个变量。此效果称为Closure。
为了避免这种情况,请在将两个变量传递给Task.Run
之前创建临时副本:
var tempJ = j;
var tempI = i;
threads[tempI][tempJ] = Task.Run(() =>
{
Calculate(tempI, tempJ, InstancesDir, FilesDir, PointSum);
});