ASP.NET MVC Состояние гонки? Фабрика Синглтон Статический словарь

1

У меня есть следующий одноэлементный класс, который служит в качестве фабрики для создания объектов в моем веб-приложении. Тем не менее, я вижу, что во время нагрузочного тестирования я получаю какое-то состояние гонки. Есть ли лучший образец, которому я должен следовать?

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
Теги:
singleton
factory

1 ответ

1

Ваш код почти такой же, как и код примера в статье 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;
        }
    }
}

Я не скомпилировал этот код, а тем более сделал стресс-тест. Если вы попробуете, сообщите мне, если это сработает!

  • 0
    На самом деле я просто решил вызвать метод Instance в моем глобальном init, чтобы убедиться, что это больше не повторится.
  • 0
    Есть несколько хороших способов реализовать это в более новых версиях .NET. Я редко вижу технику двойной проверки нуля + блокировки, используемую в наши дни. Большинство людей идут с Lazy<T> оберткой сейчас.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню