企业库的文档说:
由于Cache对象的运行方式,您可以得到保证 将调用任何后备存储 以单线程方式。这个 意味着你不必做你的 实现线程安全。
关于CacheManager:
每个方法调用都通过 CacheManager对象是线程安全的。
但是一个简单的测试证明了相反的结果:
这是我的自定义后备存储(只有Add方法相关)
public class MyStore : IBackingStore
{
volatile bool isEntered = false;
#region IBackingStore Members
public void Add(CacheItem newCacheItem)
{
if(isEntered)
throw new NotImplementedException();
isEntered = true;
Thread.Sleep(1000);
isEntered = false;
}
public int Count
{
get
{
throw new NotImplementedException();
}
}
public void Flush()
{
throw new NotImplementedException();
}
public System.Collections.Hashtable Load()
{
return new System.Collections.Hashtable();
}
public void Remove(string key)
{
throw new NotImplementedException();
}
public void UpdateLastAccessedTime(string key, DateTime timestamp)
{
throw new NotImplementedException();
}
#endregion
#region IDisposable Members
public void Dispose()
{
throw new NotImplementedException();
}
#endregion
}
这是一个通过两个不同线程访问同一个CacheManager的测试:
DictionaryConfigurationSource configSource = new DictionaryConfigurationSource();
CacheManagerSettings cacheSettings = new CacheManagerSettings();
configSource.Add(CacheManagerSettings.SectionName, cacheSettings);
CacheStorageData storageConfig = new CacheStorageData("MyStorage", typeof(MyStore));
cacheSettings.BackingStores.Add(storageConfig);
CacheManagerData cacheManagerData = new CacheManagerData("CustomCache", 120, 100, 5, storageConfig.Name);
cacheSettings.CacheManagers.Add(cacheManagerData);
cacheSettings.DefaultCacheManager = cacheManagerData.Name;
CacheManagerFactory cacheFactory = new CacheManagerFactory(configSource);
ICacheManager cacheManager = cacheFactory.CreateDefault();
Thread thread = new Thread(() =>
{
cacheManager.Add("item1", "odaiu");
});
thread.Start();
cacheManager.Add("item2", "dzaoiudoiza");
Add方法在两个不同的线程中执行两次(因为它抛出Add方法的“NotImplementedException”)。
我的代码或企业库文档有问题吗?
答案 0 :(得分:0)
由于文档对此非常明确,我相信文档。
您的证明存在缺陷,因为您正在为该类创建一个显式的多线程用例。特定接口没有什么固有的东西可以使线程安全。所以这肯定会失败。
企业库保证他们将以线程安全的方式管理接口。在内部,他们会注意管理班级的线程安全。
注意:我对这个库没有任何具体的知识,但是有明确的文档,我相信它。
答案 1 :(得分:0)
我同意JaredPar的观点,即文档说明访问是同步的,因此是不允许的。但是,如果您查看实现已交付的后备存储的源代码,您将看到它的编码期望在多线程环境中运行。所以这可能是陈旧文档的例子。
以下摘录来自EntLib 5.0中的IsolatedStorageBackingStore,认为4.1实现是相同的。为清楚起见,摘录只是一种方法,但所有对底层IsolatedStorageFile的访问都被锁定。
/// <summary>
/// Adds new item to persistence store
/// </summary>
/// <param name="storageKey">Unique key for storage item</param>
/// <param name="newItem">Item to be added to cache. May not be null.</param>
protected override void AddNewItem(int storageKey, CacheItem newItem)
{
lock (store)
{
string storageLocation = GenerateItemLocation(storageKey);
IsolatedStorageCacheItem cacheItem =
new IsolatedStorageCacheItem(store, storageLocation, this.encryptionProvider);
cacheItem.Store(newItem);
}
}