I made this small program to test parallelization.
When I hit button1 several times it ends up with an IndexOutOfBounds exception. I guess this is because I run out of memory. Why do I get this with parallelization and not with a regular foreach(button2 click)?
private void button1_Click(object sender, EventArgs e)
{
var s = Stopwatch.StartNew();
int[] nums = new int[10000];
List<int> randoms = new List<int>();
Parallel.ForEach(nums, i =>
{
randoms.Add(new Random().Next());
});
s.Stop();
label1.Text = "Added " + randoms.Count() + " randoms in "
+ s.Elapsed.Milliseconds.ToString() + " milliseconds";
}
private void button2_Click(object sender, EventArgs e)
{
var s = Stopwatch.StartNew();
int[] nums = new int[10000];
List<int> randoms = new List<int>();
foreach (var i in nums)
{
randoms.Add(new Random().Next());
}
s.Stop();
label2.Text = "Added " + randoms.Count() + " randoms in "
+ s.Elapsed.Milliseconds.ToString() + " milliseconds";
}
In your
Parallel.ForEach
code, you are concurrently modifying aList<int>
which is not threadsafe.The exception occurs when you try to add to the end of a
List
while the internal array is being resized in a different thread.Instead you should use a concurrent collection like
ConcurrentBag
orConcurrentQueue
You are modifying
randoms
in parallel. That is a bug because the list is not safe for concurrent adding.Also, IndexOutOfBounds has nothing to do with out-of-memory. You can find out all of this by looking carefully at the exception: The message tells you it is not OOM. And the stack trace tells you in which line the error occured (it was in the
Add
-line, right?).