2011-06-18 29 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是最接近的一個線程安全的列表。請記住,因爲我們正在處理未知的調度,整數將不會按順序排列。