c# - 更新 ConcurrentDictionary 中的值字段

标签 c# concurrency .net-4.0

我正在尝试像这样更新 ConcurrentDictionary 中的条目:

class Class1
{
    public int Counter { get; set; }
}

class Test
{
    private ConcurrentDictionary<int, Class1> dict =
        new ConcurrentDictionary<int, Class1>();

    public void TestIt()
    {
        foreach (var foo in dict)
        {
            foo.Value.Counter = foo.Value.Counter + 1; // Simplified example
        }
    }
}

本质上,我需要遍历字典并更新每个值的字段。我从文档中了解到我需要避免使用 Value 属性。相反,我认为我需要使用 TryUpdate,除非我不想替换整个对象。相反,我想更新对象上的一个字段。

看完this blog entry在 PFX 团队博客上:也许我需要使用 AddOrUpdate 并且在添加委托(delegate)中什么都不做。

有没有人知道如何做到这一点?


我的字典中有数以万计的对象,我需要每三十秒左右更新一次。创建新的以更新属性可能是不可行的。我需要克隆现有对象,更新它并替换字典中的对象。我还需要在克隆/添加周期期间锁定它。呸。

我想做的是迭代对象并在可能的情况下直接更新 Counter 属性。

我的最新研究让我想到了 Parallel.ForEach,这听起来不错,但它不应该用于更新状态的操作。

我还看到提到了 Interlocked.Increment,这听起来不错,但我仍然需要弄清楚如何以线程安全的方式在我的字典中的每个元素上使用它。

最佳答案

首先,解决你的锁定问题:

class Class1
{
    // this must be a variable so that we can pass it by ref into Interlocked.Increment.
    private int counter;

    public int Counter
    {
        get{return counter; }
    }

    public void Increment()
    {
        // this is about as thread safe as you can get.
        // From MSDN: Increments a specified variable and stores the result, as an atomic operation.
        Interlocked.Increment(ref counter);

        // you can return the result of Increment if you want the new value,
        //but DO NOT set the counter to the result :[i.e. counter = Interlocked.Increment(ref counter);] This will break the atomicity.
    }
}

迭代正确的值应该比迭代键值对更快。 [尽管我认为在大多数情况下,在 ConcurrentDictionary 上迭代键列表并进行查找仍然会更快。]

class Test
{
    private ConcurrentDictionary<int, Class1> dictionary = new ConcurrentDictionary<int, Class1>();

    public void TestIt()
    {
        foreach (var foo in dictionary.Values)
        {
            foo.Increment();
        }
    }

    public void TestItParallel()
    {
        Parallel.ForEach(dictionary.Values,x=>x.Increment() );
    }

}

关于c# - 更新 ConcurrentDictionary 中的值字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2901289/

相关文章:

java - 线程阻塞时会做什么

c# - 在继续代码之前等待空闲线程槽

c# - 在 Silverlight 中,如何从模板中获取动画并通过 C# 代码使用它?

c# - 初学者需要的降低耦合简单示例

c# - 一个类应该包含它自己的集合吗?

api - 如何在每个例程调用 api 的情况下并行运行 10000 个 goroutines?

entity-framework - 删除具有一对多关系的 child 的 parent

c# - 更新数据库上的 ConnectionString 属性尚未初始化

c# - 基类 list<type> 属性与派生类 list<衍生类型> 属性之间的传输

asynchronous - iPhone - GCD 将异步操作发送到串行调度队列