代码之家  ›  专栏  ›  技术社区  ›  Vin

在Parallel.ForEach中使用哈希表?

  •  7
  • Vin  · 技术社区  · 15 年前

    我有一个Parallel.ForEach循环在体内运行一个密集的操作。

    该操作可以使用哈希表存储值,并且可以对其他连续循环项重复使用。我在密集操作完成后添加到哈希表中,下一个循环项可以在哈希表中查找并重用对象,而不是再次运行密集操作。

    Hashtable myTable = new Hashtable;
    Parallel.ForEach(items, (item, loopState) =>
    {
        // If exists in myTable use it, else add to hashtable
        if(myTable.ContainsKey(item.Key))
        {
           myObj = myTable[item.Key];
        }
        else
        {
           myObj = SomeIntensiveOperation();
           myTable.Add(item.Key, myObj); // Issue is here : breaks with exc during runtime
        }
        // Do something with myObj
        // some code here
    }
    

    TPL库中必须有一些API和属性设置,可以处理这种情况。有?

    4 回复  |  直到 15 年前
        1
  •  18
  •   Sam Harwell    15 年前

    你在找什么 System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>

    编辑:结果可能如下所示:

    ConcurrentDictionary<T,K> cache = ...;
    Parallel.ForEach(items, (item, loopState) =>
    {
        K value;
        if (!cache.TryGetValue(item.Key, out value))
        {
            value = SomeIntensiveOperation();
            cache.TryAdd(item.Key, value);
        }
    
        // Do something with value
    } );
    

    如果元素在 items 并不是所有人都有独特的个性 item.Key 那么 SomeIntensiveOperation 强化手术 如果

        2
  •  4
  •   Hannoun Yassir    15 年前
        3
  •  3
  •   joshperry    15 年前

    使用ReaderWriterLock,这对于在短时间内进行多次读取和少量写入的工作具有良好的性能。您的问题似乎符合此规范。

    ReaderWriterLockSlim on MSDN

    我想我会写一些代码。。。

    ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
    Hashtable myTable = new Hashtable();
    Parallel.ForEach(items, (item, loopState) =>
    {
        cacheLock.EnterReadLock();
        MyObject myObj = myTable.TryGet(item.Key);
        cacheLock.ExitReadLock();
    
        // If the object isn't cached, calculate it and cache it
        if(myObj == null)
        {
           myObj = SomeIntensiveOperation();
           cacheLock.EnterWriteLock();
           try
           {
               myTable.Add(item.Key, myObj);
           }
           finally
           {
               cacheLock.ExitWriteLock();
           }           
        }
        // Do something with myObj
        // some code here
    }
    
    static object TryGet(this Hashtable table, object key)
    {
        if(table.Contains(key))
            return table[key]
        else
            return null;
    }
    
        4
  •  1
  •   Dario    15 年前

    除了使用(或多或少显式的)锁(同步哈希表只是用锁覆盖所有方法),我看不到其他正确的选择。

    另一个选择是允许字典不同步。竞争条件不会损坏字典,它只需要代码进行一些多余的计算。配置代码以检查锁定或丢失的备忘录是否会产生更糟糕的效果。

    推荐文章