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
pointvariable 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,pointmay be assigned a value, and then the context switch to run with anotherpandpointis reassigned to another value and when the thread for previouspis back,pointno longer has the correct value.You need to ensure it's immutable, probably by declaring it inside
Parallel.ForEach.