2011-06-18 32 views
4

我写了一些代码:的Parallel.For失败(C#)

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>(); 
      } 
     } 
    } 

但不预期的结果(

不Console.WriteLine调用

什么是之前所有周期的完成使用Parallel.For的问题?

回答

1

List<T>不是线程安全的类。您应该使用Concurrent集合中的一个,或者实现您自己的同步。

详见this answerParallel.For

7

您正在运行到什么被称为Race Condition。由于.Net中的List集合不是线程安全的,因此它的操作(如Add())不是原子的。基本上,在一个线程上调用Add()可以在完成之前销毁另一个线程的Add()。您需要为您的代码提供线程安全的并发集合。

试试这个:

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是最接近的一个线程安全的列表。请记住,因为我们正在处理未知的调度,整数将不会按顺序排列。