My program must check the state of all elements in array. When I use foreach
it's ok, but in Parallel.ForEach
and Parallel.For
it throws index out of bounds exception.
This code works:
foreach (var p in _currentSpherePoints)
{
point = p + center;
point.X = (point.X + _field.GetLength((int)VectorInt.Dimension.X)) % _field.GetLength((int)VectorInt.Dimension.X);
point.Y = (point.Y + _field.GetLength((int)VectorInt.Dimension.Y)) % _field.GetLength((int)VectorInt.Dimension.Y);
point.Z = (point.Z + _field.GetLength((int)VectorInt.Dimension.Z)) % _field.GetLength((int)VectorInt.Dimension.Z);
if (_field[point.X, point.Y, point.Z] != 0)
{
isCrossed = true;
break;
}
}
And this not:
Parallel.ForEach(_currentSpherePoints, (p, state) =>
{
point = p + center;
point.X = (point.X + _field.GetLength((int)VectorInt.Dimension.X)) % _field.GetLength((int)VectorInt.Dimension.X);
point.Y = (point.Y + _field.GetLength((int)VectorInt.Dimension.Y)) % _field.GetLength((int)VectorInt.Dimension.Y);
point.Z = (point.Z + _field.GetLength((int)VectorInt.Dimension.Z)) % _field.GetLength((int)VectorInt.Dimension.Z);
if (_field[point.X, point.Y, point.Z] != 0)
{
isCrossed = true;
state.Stop();
}
});
public bool IsSphereCrossed(VectorInt center)
{
bool isCrossed = false;
var point = new VectorInt(0, 0, 0);
Parallel.ForEach(_currentSpherePoints, (p, state) =>
{
point = p + center;
point.X = (point.X + _field.GetLength((int)VectorInt.Dimension.X)) % _field.GetLength((int)VectorInt.Dimension.X);
point.Y = (point.Y + _field.GetLength((int)VectorInt.Dimension.Y)) % _field.GetLength((int)VectorInt.Dimension.Y);
point.Z = (point.Z + _field.GetLength((int)VectorInt.Dimension.Z)) % _field.GetLength((int)VectorInt.Dimension.Z);
if (_field[point.X, point.Y, point.Z] != 0)
{
isCrossed = true;
state.Stop();
}
});
return isCrossed;
}
As you see, I don't change collection, so I don't know, where there is a problem.
_currentSpherePoints
contains my own Vector class.
Now that you have shared the whole function, here's the problem:
Notice
point
variable is shared between all runs ofParallel.ForEach
, which you can't be sure to be the same for each whole run. For example, in one thread,point
may be assigned a value, and then the context switch to run with anotherp
andpoint
is reassigned to another value and when the thread for previousp
is back,point
no longer has the correct value.You need to ensure it's immutable, probably by declaring it inside
Parallel.ForEach
.