在webservice中使用ConcurrentDictionary
本文关键字:ConcurrentDictionary webservice | 更新日期: 2023-09-27 18:05:12
我已经构建了一个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,我想知道如果我用这个代替,它会解决这个问题吗?
另一点需要注意的是,我不能使用锁,因为它是静态的!
理论上,. net ConcurrentDictionary类应该为您工作。这是一个线程安全字典实现。
你可以在这里了解更多关于。net并发集合的信息:http://msdn.microsoft.com/en-us/library/system.collections.concurrent(v=vs.110).aspx
允许以线程安全的方式进行一次初始化的简单方法是使用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]);
}
但是在一般设计中要避免静态
我认为使用锁对象没有问题,只是让它也是静态的,并确保锁内的代码尽可能快。
我已经改变了字典的填充方式,使其更具可读性,但这更多的是个人问题。(似乎更适合答案部分)
例子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);
}