在Web服务中使用ConcurrentDictionary

时间:2014-05-27 06:32:37

标签: c# sharepoint dictionary

我已经构建了一个Web服务,它从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;
        }
    }

这个词典正由我创建的两种不同的服务方法使用。

从测试客户端分别调用这些方法时实际上没有问题。但是,这里显而易见的是,当对Web服务进行多次调用时,它会引发异常!

我碰巧在MSDN中遇到过ConcurrentDictionay,并想知道如果我用它而不是,它会解决这个问题吗?

需要注意的另一点是我不能使用锁,因为它是静态的!

3 个答案:

答案 0 :(得分:0)

理论上,.NET ConcurrentDictionary类应该适合您。它是一个线程安全的字典实现。

您可以在此处了解有关.NET并发集合的更多信息:http://msdn.microsoft.com/en-us/library/system.collections.concurrent(v=vs.110).aspx

答案 1 :(得分: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]);

}

然而,在您的一般设计中避免使用静态

答案 2 :(得分: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);
}