2012-03-11 99 views
1

這是一些樣品的測試軟件,我想學習Parallel.Foreach循環功能Parallel.ForEach循環行爲

static void Main(string[] args) 
{ 
    List<string> Months = new List<string>() 
    { 
     "Jan", "Feb", "Mar", "Apr", "May", "June" 
    }; 
    Parallel.ForEach(Months, (x) => ProcessRandom(x)); 
    Console.ReadLine(); 
} 

public static void ProcessRandom(string s) 
{ 
    Random r = new Random(); 
    int i = r.Next(1, 100); 
    Thread.Sleep(1000); 
    Console.WriteLine(string.Format("Month Name {0} and Random ID assigned {1}", s, i)); 
} 

我對並行的foreach的理解是,它會運行與從列表中選擇參數ProcessRandom方法在平行下。該方法內的所有變量都是獨立的,它們將獨立運行。但是當我運行時,我發現存儲在整數'i'中的隨機值對於來自月份列表中的幾個輸入端顯示相同,或者可能是2將具有不同的隨機值。爲什麼這是這樣的行爲。並行循環不應該爲每次迭代創建新的隨機值。如果我使用parallelOptions並將MaxDegree的Parallelism設置爲1,那麼我在變量'i'中看到不同的值。

請指導我理解並行循環。

+1

我不認爲這是parallel.foreach的問題,而是與隨機。如果對循環使用相同的隨機實例,則可能會看到更多可預測的結果。 – 2012-03-11 03:03:55

+0

如果使用靜態函數,則可以使它們在自己的容器中運行。 – 2012-03-11 03:09:10

+0

@ Gary.S,有一個實例無法正常工作,因爲「隨機」不是線程安全的。 – svick 2012-03-11 03:22:20

回答

2

發生這種情況是因爲Random不是真正的隨機而是僞隨機的(http://msdn.microsoft.com/en-us/library/system.random.aspx)。這個確切的問題在MSDN文章的評論中提到。當同時創建多個實例並且兩個實例都調用.Next()時,它們可能會以相同的結果結束(由於系統時鐘分辨率有限)。爲了解決這個問題,我們應該爲每次迭代創建一個獨特的種子。爲此,你可以做這樣的事情(但也有很多方法對皮膚這隻貓):

static void Main(string[] args) 
{ 
    List<string> Months = new List<string>() { "Jan", "Feb", "Mar", "Apr", "May", "June" }; 
    Parallel.ForEach(Months, (x) => ProcessRandom(x)); 
    Console.ReadLine(); 
} 

public static void ProcessRandom(string s) 
{    
    Random r = new Random(s.GetHashCode()); 
    int i = r.Next(1, 100); 
    Thread.Sleep(1000); 
    Console.WriteLine(string.Format("Month Name {0} and Random ID assigned {1}", s, i)); 
} 

**注意這個例子並不能保證唯一性,但只是顯示的方式來生成種子值**

+3

請注意,Random.Next()不是線程安全的,因此以這種方式使用它可能會有不可預測性結果。 – dlev 2012-03-11 03:16:23

+0

@dlev確實,更好的例子是爲每次迭代創建一個具有唯一種子的Random對象。 – 2012-03-11 03:42:33

+0

謝謝你的解釋! – 2012-03-11 19:07:57

相關問題