From the information you provided, I understand that you want to have an Foo output array with a size equal to the input byte array? It's right?
, . , , .
, , :
X [i] X [j], Y [i]

Scatter/Gather, , .
, Foo [] Parallel.For not ForEach .
.
List<byte[]> inputArray = new List<byte[]>();
int[] outputArray = new int[inputArray.Count];
var waitHandle = new ManualResetEvent(false);
int counter = 0;
Parallel.For(0, inputArray.Count, index =>
{
outputArray[index] = DoOperation(inputArray[index]);
if(Interlocked.Increment(ref counter) == inputArray.Count -1)
{
waitHandle.Set();
}
});
waitHandler.WaitOne();
var outputList = outputArray.ToList();