Parallel .For fail (C #)

I wrote the code:

class Program { public const int count = 3000; static List<int> list = new List<int>(); static void DoWork(int i) { list.Add(i); } static void Main(string[] args) { while (true) { Stopwatch s = new Stopwatch(); s.Start(); Parallel.For(0, count + 1, DoWork); s.Stop(); Console.WriteLine("\n Elapsed: " + s.Elapsed.ToString()); Console.WriteLine("Expected: {0}", count + 1); Console.WriteLine("count: {0}", list.Count); Console.ReadKey(); list = new List<int>(); } } } 

but the results are not expected (

Not all loops are complete before Console.WriteLine calls

What is the problem using Parallel.For?

+4
source share
3 answers

You are faced with what is called Race Condition . Because the List collection in .Net is not thread safe, its operations, such as Add() , are not atomic. Basically, calling Add () in one thread can destroy another Add () thread before it finishes. You need thread safe data collection for your code.

Try the following:

 using System.Threading.Tasks; class Program { public const int count = 3000; static ConcurrentBag<int> bag = new ConcurrentBag<int>(); static void DoWork(int i) { bag.Add(i); } static void Main(string[] args) { while (true) { Stopwatch s = new Stopwatch(); s.Start(); Parallel.For(0, count + 1, DoWork); s.Stop(); Console.WriteLine("\n Elapsed: " + s.Elapsed.ToString()); Console.WriteLine("Expected: {0}", count + 1); Console.WriteLine("count: {0}", bag.Count); Console.ReadKey(); bag = new ConcurrentBag<int>(); } } } 

ConcurrentBag is the closest to a thread safe list. Just remember, since we are dealing with unknown planning, integers will not be in order.

+7
source

The List<> class is not a stream preservation. You cannot change it in a parallel loop (no problem). Use the System.Collections.Concurrent namespace form collection

+1
source

List<T> not a thread safe class. You must use one of the parallel collections or implement your own synchronization.

More on Parallel.For

see this answer .
+1
source

All Articles