本文介绍了任务铁血阵列 - 并发问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义线程的交错数组(这样每个线程都可以在自己的目录树操作)以这种方式

 任务[] []线程=新任务[InstancesDir.Length] [];
的for(int i = 0; I< InstancesDir.Length;我++)
{
    线程[我] =新任务[InstancesDir [I] .Length]。
}
的for(int i = 0; I< FilesDir.Length;我++)
{
    对于(INT J = 0; J< FILESDIR [I] .Length; J ++)
    {
        螺纹[I] [J] = Task.Run(()=>
        {
            计算(I,J,InstancesDir,FILESDIR,PointSum);
        });
    }
    Task.WaitAll(线程[I]);
}
 

但在计算我总是得到的J值> = FILESDIR [I] .Length。我还检查的对象是按值传递除数组。什么可能是一个解决方法,这有什么能为这种现象的原因是什么?

PS。引入一个共享锁可能会缓解并发性问题,帮助,但我想知道这种行为的原因。

解决方案

这是不是并发问题,因为你的循环执行在单个线程。这是因为拉姆达EX pression是收了你的Ĵ变量。这种效应被称为关闭

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

  VAR tempJ = j的;
VAR TEMPI =我;

螺纹[TEMPI] [tempJ] = Task.Run(()=>
{
    计算(TEMPI,tempJ,InstancesDir,FILESDIR,PointSum);
});
 

I am defining a jagged array of threads (such that each thread can operate on the directory tree of its own) in this manner

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]);
}

But in calculate i always get value of j >= FilesDir[i].Length . I have also checked that objects are passed by value except arrays. What could be a workaround for this and what could be the reason for this behavior?

PS. Introducing a shared lock might help in mitigation the concurrency issue but i want to know about the reason for such behavior.

解决方案

This isn't a concurrency issue, as your for loop is executing on a single thread. This happens because the lambda expression is closing over your i and j variables. This effect is called Closure.

In order to avoid it, create a temp copy before passing both variables to Task.Run:

var tempJ = j;
var tempI = i;

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

这篇关于任务铁血阵列 - 并发问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 06:44