2013-04-11 47 views
2

我現在已經睜大眼睛瞎了,所以請幫助。從異步方法返回相同的值

當我在一個循環內調用兩次這個方法時,它會返回相同的值。爲什麼?

public async Task<int> RollDice() { 
    var rnd = new Random(); 
    var selected = 0; 

    await Task.Run(() => { 
     selected = rnd.Next(1, 6); 
     }); 

    return selected; 
} 

回答

6

你必須初始化使用相同的種子,並因此返回相同的值,以防止它被初始化一遍一遍所述方法外的Random對象。

重要的是要注意到,作爲LukeH在評論中正確添加,那System.Random線程安全的,不應該在單獨的線程任務之間共享是非常重要的。

+0

doh,當然:) – danielovich 2013-04-11 09:02:49

+2

正確,但是......要小心「System.Random」不是線程安全的,因此在多個線程池任務之間共享單個實例(通過Task.Run)不是一個好主意。 – LukeH 2013-04-11 09:03:08

+0

@LukeH謝謝,我已經編輯了我的答案。 – 2013-04-11 09:05:57

2

您正在使用Random類的兩個實例。使用parameterless constructor,隨機數發生器使用基於系統時鐘的值來播種。

這意味着如果您不斷創建兩個Random實例,它們將使用相同的值進行初始化,因爲系統時鐘具有有限的分辨率。具有相同的種子意味着這兩個實例將產生相同的結果序列。

一些谷歌搜索顯示,使用Random跨線程會導致其破裂,返回零的循環順序,因此,如果你要多線程代碼的這個特殊的一部分,您可能想看看this article如何創建一個Random類的單線程安全版本。