【问题标题】:How to correctly handle adding new item to dictionary?如何正确处理向字典添加新项目?
【发布时间】:2012-06-17 03:33:10
【问题描述】:

我有一个使用静态类作为缓存的 ASP.NET 应用程序。该静态类内部是内部字典,其中包含缓存的对象。当然,静态类中还有 Add/Remove/Clear 之类的方法...看起来如下:

public static class CacheManager
{
    private static Dictionary<string, object> cacheItems = new Dictionary<string, object>();

    private static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();

    public static Dictionary<string, object> CacheItems
    {
        get
        {
            return cacheItems;
        }
    }

    public static void AddCacheItem(string key, object data)
    {
        locker.EnterWriteLock();
        try
        {
            cacheItems.Add(key, data);
        }
        finally
        {
            locker.ExitWriteLock();
        }
    }

    ...
}

当 ASP.NET 应用程序运行时,这些项目被添加到缓存(字典)中。我只想问我是否应该在 Add 方法中检查是否已经以这种方式添加了密钥:

    public static void AddCacheItem(string key, object data)
    {
        locker.EnterWriteLock();
        try
        {
            if (!cacheItems.ContainsKey(key))
            {
                cacheItems.Add(key, data);
            }
        }
        finally
        {
            locker.ExitWriteLock();
        }
    }

还是在第一个代码 sn-p 中保持原样?

提前谢谢你。

【问题讨论】:

  • 我更关心从CacheItems 属性读取的代码将如何进入读锁...
  • 你的意思是我也应该放一些同步的东西?
  • ConcurrentDictionary 怎么样。或者你没有使用.Net 4.0? msdn.microsoft.com/en-us/library/dd287191.aspx
  • 添加与否对调用者有影响吗?
  • 由于您要公开字典,因此所有同步的赌注都已关闭(即使所有读取都已同步),您仍然可以在不同步的情况下添加项目。德墨忒耳法则可以避免您可能面临的问题的一个很好的例子

标签: c# asp.net dictionary add


【解决方案1】:

您可以再实现一种方法 TryAdd

public static bool TryAddCacheItem(string key, object data)
{
    locker.EnterWriteLock();
    try
    {
        if (cacheItems.ContainsKey(key))
        {
            return false;
        }
        cacheItems.Add(key, data);
        return true;
    }
    finally
    {
        locker.ExitWriteLock();
    }
}

另外我建议使用ConcurrentDictionaryHere 是 ConcurrentDictionary 的代码。

【讨论】:

  • 我明白了,但是客户端应该使用哪一个,为什么我的第二个代码sn-p不够?
  • 这完全取决于 AddCacheItem 方法的职责。在 k0stya 代码中,如果失败,它会通知调用类。问题是您的逻辑是否需要知道,如果添加缓存项失败。
  • 您对使用 ConcurrentDictionary 的建议是可以的,但我们使用 .NET Framework 3.5。
  • Eiver,我已经理解 k0stya 写的内容了。我们实际上不需要知道 AddCacheItem 方法是否失败。我们只应确保不添加重复键。在这种情况下,我的第二个代码 sn-p 应该足够了吗?
  • 那么第二个就够了。无论如何看看code.google.com/p/codesmith/source/browse/trunk/Templates/…
【解决方案2】:

只需执行两次:

cacheItems.Add(key, data);

...你会知道答案的。基本上,异常将被 try/finally 块抛出并捕获。我个人会使用 if 语句,而不是将所有逻辑责任放在 try 块上,但这是一个偏好问题......

【讨论】:

  • 是的。我做到了,如果我不使用我的第二个代码 sn-p 会有一个例外。这就是我问这个的原因。
  • 嗯,通常我会为意外的东西使用异常。如果您使用 try 块,那么通常您不会知道发生了什么。 dictionary.add() 很简单,因为它只是抛出 ArgumentNullException 或 ArgumentException。其他方法可能会出于不同的原因(甚至只是异常)抛出相同的异常类型。我会说 - 使用 if 语句,因为你输入“else”语句然后你就知道发生了什么。在 socket.connect() 之类的情况下,我会使用 try catch 块,因为 if(socket.CanConnect()) 是不可能的
猜你喜欢
  • 2012-11-18
  • 2014-09-14
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
  • 2020-08-28
相关资源
最近更新 更多