2012-06-28 42 views
9

最近我遇到了一個懶惰的singelton類的問題,初始化一個字典,第二個線程會在實際填充之前嘗試使用它。所以我通過Lazy<T>類實現了變量初始化。正在使用懶惰<T>性能不好?

這裏是我的代碼:

private static Dictionary<string, string> GroupDefaults 
{ 
    get { return mGroupDefaults.Value; } 
} 
private static Lazy<Dictionary<string, string>> mGroupDefaults = 
    new Lazy<Dictionary<string,string>>(delegate 
    { 
     Dictionary<string, string> defaults = new Dictionary<string, string>(); 
     foreach (KeyValuePair<string, UnitGroup> groupDef in Groups) 
      defaults.Add(groupDef.Key, groupDef.Value.First().Key); 
     return defaults; 
    }); 

這個固定的問題,現在我正在考慮將這個礦的慣常做法,以使用Lazy<T>類的任何地方我做延遲初始化,以避免任何可能的線程問題。所以基本上我想知道這是否是好的/常見的做法?或者它會對業績或其他事情產生影響?

回答

10

如果不知道你有什麼類型的性能限制很難說,但根據我的經驗,一次初始化很少是一個瓶頸(因爲根據定義它只發生一次)。Lazy<T>是爲了向你提供這個確切的服務,所以我會建議使用它。

+0

所以它的一個好習慣使用懶惰類? –

+2

@ AlexHopeO'Connor這就是爲什麼它被添加!使用這個類的缺點是,字段/屬性的聲明變得有點混亂(正如你所看到的),但是在性能方面,它是穩定的。 – dlev

+2

這就是我需要聽到的,只是我在其他人的代碼中沒有看到它的許多例子。 –

1

我想你可能會使用懶惰而不是它的用途。懶惰是用於某些情況下,有些東西的初始化成本很高,但有可能在對象的生命週期中不能使用它。

如果你總是叫GroupDefaults至少一次每它的壽命更好的方法是在容器的生命週期的開始在後臺線程來初始化GroupDefaults,並希望它完成初始化之前是做(我知道有這是一個類,但我需要挖掘到MSDN找到它)

+1

雖然我同意這是預期的用例,它*還*正確實現線程安全的初始化,所以你不必擔心關於你自己這樣做。 – dlev

+0

我正在從另一個線程初始化它,但是,在並行加載的其他東西試圖訪問它之前,初始化不會完成。這是一個非常奇怪的情況,我無法按順序加載,因爲它會爲加載時間增加相當長的時間。因此,我產生了許多線程,因爲GroupDefaults沒有被初始化,所以在它們被阻擋之前做了大量的工作,從而導致總體上更快的加載時間。然而,我基本上是問使用這個類會有什麼負面影響?它的缺點是什麼? –

2

如果這是一個單身人士,static constructor可能是你想要的。喜歡的東西:

class MySingleton 
{ 
    static MySingleton() 
    { 
     Instance().InitDict(); 
    } 
} 
3

從文檔,我發現以下幾點:

如果沒有委託在Lazy構造過去了, 包裝類型是使用Activator.CreateInstance創建時的價值屬性首先被訪問。 如果該類型沒有默認構造函數,則會引發運行時異常。

Activator.CreateInstance是一個臭名昭着的性能不好的方法。但是,對於你的情況來說,這似乎不成問題,無論如何,正如dlev所說,調用方法一次不會成爲問題。我還沒有看到Lazy<T>經常使用,但我沒有看到任何理由不使用它在你的情況。