锯齿状的任务数组 - 并发问题

时间:2015-02-04 06:41:32

标签: c# .net multithreading task-parallel-library task

我正在以这种方式定义一个参差不齐的线程数组(这样每个线程可以在它自己的目录树上运行)

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。引入共享锁可能有助于缓解并发问题,但我想知道这种行为的原因。

1 个答案:

答案 0 :(得分:3)

  

但是在计算中我总是得到j的值&gt; = FilesDir [i] .Length

这不是并发问题,因为您的for循环正在单个线程上执行。发生这种情况是因为lambda表达式正在关闭ij个变量。此效果称为Closure

为了避免这种情况,请在将两个变量传递给Task.Run之前创建临时副本:

var tempJ = j;
var tempI = i;

threads[tempI][tempJ] = Task.Run(() =>
{
    Calculate(tempI, tempJ, InstancesDir, FilesDir, PointSum);
});