任务的铁血阵列 - 并发问题(Jagged array of tasks - Concurrency

2019-10-21 18:20发布

我以这种方式限定线程的交错数组(例如每个线程可以在其自身的目录树进行操作)

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的值> = FILESDIR [I]。长度。 我还检查的对象是按值除传递数组。 有什么能解决类似的问题,什么可能是这种现象的原因是什么?

PS。 介绍一个共享锁可能会缓解有助于并发性问题,但我想知道对这种行为的原因。

Answer 1:

但在计算我总是得到J>时= FILESDIR [I]。长度的价值

这不是一个并发问题,因为你for循环在单个线程执行。 这是因为lambda表达式正在关闭在你ij变量。 这种效应被称为封闭

为了避免它,这两个变量传递给之前创建一个临时副本Task.Run

var tempJ = j;
var tempI = i;

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


文章来源: Jagged array of tasks - Concurrency Issues