У меня есть следующий одноэлементный класс, который служит в качестве фабрики для создания объектов в моем веб-приложении. Тем не менее, я вижу, что во время нагрузочного тестирования я получаю какое-то состояние гонки. Есть ли лучший образец, которому я должен следовать?
public class SearchProviderFactory {
private static SearchProviderFactory factory = null;
private static Dictionary<string, Type> providerMap = new Dictionary<string, Type>();
private SearchProviderFactory() {
// Error on the line below
providerMap.Add("company_name", Type.GetType("MyApp.CompanySearchProvider"));
providerMap.Add("job_title", Type.GetType("MyApp.JobTitleSearchProvider"));
}
public static SearchProviderFactory Instance {
get {
if (factory == null) {
factory = new SearchProviderFactory();
}
return factory;
}
}
}
Я получаю следующую ошибку, хотя кажется, что частный конструктор никогда не должен вызываться более одного раза.
System.ArgumentException: An item with the same key has already been added.
at System.Collections.Generic.Dictionary'2.Insert(TKey key, TValue value, Boolean add)
at MyApp.SearchProviderFactory..ctor() in c:\MyApp\_scm\app\src\trunk\MyApp\SearchProviderFactory.cs:line 7
Ваш код почти такой же, как и код примера в статье MSDN, посвященный реализации Singleton в С#. Эта статья довольно приятная, я рекомендую ее.
Их рекомендация состоит в том, чтобы добавить оператор lock() для реализации критического раздела с использованием. В вашем коде это будет примерно так:
public class SearchProviderFactory {
private static volatile SearchProviderFactory factory;
private static Dictionary<string, Type> providerMap = new Dictionary<string, Type>();
private SearchProviderFactory() {
// Error on the line below
providerMap.Add("company_name", Type.GetType("MyApp.CompanySearchProvider"));
providerMap.Add("job_title", Type.GetType("MyApp.JobTitleSearchProvider"));
}
public static SearchProviderFactory Instance {
get {
if (factory == null) {
lock (providerMap)
{
if (factory == null) {
factory = new SearchProviderFactory();
}
}
}
return factory;
}
}
}
Я не скомпилировал этот код, а тем более сделал стресс-тест. Если вы попробуете, сообщите мне, если это сработает!
Lazy<T>
оберткой сейчас.