使用我认为在 Implementing the Singleton Pattern in C# 上世界上最好的东西很棒的文章,我一直在成功使用以下类将用户定义的数据保存在内存中(对于很少修改的数据):
public class Params
{
static readonly Params Instance = new Params();
Params()
{
}
public static Params InMemory
{
get
{
return Instance;
}
}
private IEnumerable<Localization> _localizations;
public IEnumerable<Localization> Localizations
{
get
{
return _localizations ?? (_localizations = new Repository<Localization>().Get());
}
}
public int ChunkSize
{
get
{
// Loc uses the Localizations impl
LC.Loc("params.chunksize").To<int>();
}
}
public void RebuildLocalizations()
{
_localizations = null;
}
// other similar values coming from the DB and staying in-memory,
// and their refresh methods
}
我的用法看起来像这样:
var allLocs = Params.InMemory.Localizations; //etc
每当我更新数据库时,都会调用 RefreshLocalizations,因此只有部分内存存储被重建。在调用 RefreshLocalizations 时,我有一个单一生产环境,似乎在大约 10 个生产环境中表现不正常,根本不刷新,但这似乎也是断断续续的,非常完全奇怪。
我目前怀疑单例,我认为它做得很好,所有单元测试都证明单例机制、刷新机制和 RAM 性能都按预期工作。
也就是说,我认为有这些可能性:
- 当这位客户说他们的环境没有使用负载平衡时,他在撒谎,这是一种我不希望内存中的东西正常工作的设置(对吧?)
- 他们的 IIS 中有一些非标准的池配置,我正在对其进行测试(也许在 Web Garden 设置中?)
- 单例以某种方式失败,但不确定如何失败。
有什么建议吗?
.NET 3.5 所以没有太多的平行果汁可用,现在还没有准备好使用响应式扩展
Edit1:根据建议,getter 看起来像这样吗:
public IEnumerable<Localization> Localizations
{
get
{
lock(_localizations) {
return _localizations ?? (_localizations = new Repository<Localization>().Get());
}
}
}
最佳答案
为了扩展我的评论,下面是如何使 Localizations
属性线程安全:
public class Params
{
private object _lock = new object();
private IEnumerable<Localization> _localizations;
public IEnumerable<Localization> Localizations
{
get
{
lock (_lock) {
if ( _localizations == null ) {
_localizations = new Repository<Localization>().Get();
}
return _localizations;
}
}
}
public void RebuildLocalizations()
{
lock(_lock) {
_localizations = null;
}
}
// other similar values coming from the DB and staying in-memory,
// and their refresh methods
}
关于c# - 持久内存缓存上的单例模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8821611/