Использование ConcurrentDictionary в веб-сервисе

1

Я создал веб-сервис, который инициализирует набор значений конфигурации из WebConfig следующим образом:

  Dictionary<string, string> _configSPSynker {
        get {
            if (_configSPSynker2 != null) return _configSPSynker;
            _configSPSynker2 = (from k in      System.Configuration.ConfigurationManager.AppSettings.AllKeys
                               where k.Length > 9 && k.Substring(0, 9) == "SPSynker_"
                               select k).ToDictionary(k => k.Substring(9), k => System.Configuration.ConfigurationManager.AppSettings[k]);
            return _configSPSynker2;
        }
    }

Этот словарь используется двумя различными способами, которые я создал.

На самом деле нет проблем при вызове этих методов отдельно от тестового клиента. Однако здесь очевидно, что он генерирует исключение, когда в веб-сервис совершается более одного вызова!

Мне довелось встретить ConcurrentDictionay в MSDN и хотелось бы знать, что если бы я использовал это вместо этого, решит ли он эту проблему?

Еще один момент, который следует отметить, заключается в том, что я не могу использовать блокировку, потому что она статична!

Теги:
dictionary
sharepoint

3 ответа

0
Лучший ответ

Теоретически класс.NET ConcurrentDictionary должен работать на вас. Это реализатор словарных словарей.

Подробнее о сборках.NET можно узнать здесь: http://msdn.microsoft.com/en-us/library/system.collections.concurrent(v=vs.110).aspx

0

Я не вижу проблем с использованием объекта блокировки, просто сделайте его также статическим и убедитесь, что код внутри замка работает как можно быстрее.

Я изменил способ заполнения словаря, чтобы сделать его более читаемым, но это скорее личная проблема. (Кажется, лучше подходит к разделу ответа)

Пример 1 (Ваша текущая ситуация):

private static Dictionary<string, string> configSPSynker;
private static readonly object lockObject = new object();

internal static Dictionary<string, string> ConfigSPSynker
{
    get
    {
        lock (lockObject)
        {
            // check inside the lock, because a race condition can occur.
            if (configSPSynker == null)
            {
                var dictionary = new Dictionary<string,string>();
                foreach (var key in ConfigurationManager.AppSettings.AllKeys)
                {
                    if (key.Length > 9 && key.Substring(0, 9) == "SPSynker_")
                        dictionary.Add(key.Substring(9),
                                       ConfigurationManager.AppSettings[key]);
                }
                configSPSynker = dictionary;
            }
        }
        return configSPSynker;
    }
}

Тем не менее, я предпочел бы предложить другой подход, чтобы не раскрывать словарь, а метод, который возвращает значение для запрошенного ключа, поскольку он не позволяет вызывающему абоненту получить доступ и изменить словарь:

Пример 2:

private static Dictionary<string, string> configSPSynker;
private static readonly object lockObject = new object();

internal static bool TryGetValue(string key, out string value)
{
    lock (lockObject)
    {
        // check inside the lock, because a race condition can occur.
        if (configSPSynker == null)
        {
            var dictionary = new Dictionary<string, string>();
            foreach (var k in ConfigurationManager.AppSettings.AllKeys)
            {
                if (k.Length > 9 && k.Substring(0, 9) == "SPSynker_")
                    dictionary.Add(k.Substring(9),
                                   ConfigurationManager.AppSettings[k]);
            }
            configSPSynker = dictionary;
        }
    }
    return configSPSynker.TryGetValue(key, out value);
}
0

Легкий способ разрешить инициализацию один раз в потокобезопасном режиме - использовать Lazy. Если словарь доступен только для чтения после инициализации, вам не нужно использовать параллельный словарь.

static Lazy<Dictionary<string, string>> ConfigSPSSynker = new Lazy<Dictionary<string, string>>( ()=> LoadConfigSettings() );

static Dictionary<string, string> LoadConfigSettings()
{
 return  (from k in      System.Configuration.ConfigurationManager.AppSettings.AllKeys
                           where k.Length > 9 && k.Substring(0, 9) == "SPSynker_"
                           select k).ToDictionary(k => k.Substring(9), k => System.Configuration.ConfigurationManager.AppSettings[k]);

}

Однако в вашем общем дизайне избегайте статики

Ещё вопросы

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