在ConcurrentDictionary中更新值的字段 [英] Updating fields of values in a ConcurrentDictionary

查看:1806
本文介绍了在ConcurrentDictionary中更新值的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想更新ConcurrentDictionary中的条目,如下所示:

I am trying to update entries in a ConcurrentDictionary something like this:

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,除了我不想替换整个对象。

Essentially I need to iterate over the dictionary and update a field on each Value. I understand from the documentation that I need to avoid using the Value property. Instead I think I need to use TryUpdate except that I don’t want to replace my whole object. Instead, I want to update a field on the object.

阅读在PFX团队博客上的这个博客条目:也许我需要使用AddOrUpdate,只是在添加代理什么都不做。

After reading this blog entry on the PFX team blog: Perhaps I need to use AddOrUpdate and simply do nothing in the add delegate.

有没有人知道如何这样做?

Does anyone have any insight as to how to do this?

成千上万的字典中的对象,我需要更新每三十秒左右。创建新的为了更新属性可能不可行。我需要克隆现有的对象,更新它并替换字典中的一个。我还需要在克隆/添加循环期间锁定它。 Yuck。

I have tens of thousands of objects in the dictionary which I need to update every thirty seconds or so. Creating new ones in order to update the property is probably not feasible. I would need to clone the existing object, update it and replace the one in the dictionary. I’d also need to lock it for the duration of the clone/add cycle. Yuck.

我想做的是迭代对象,如果可能的话直接更新Counter属性。

What I’d like to do is iterate over the objects and update the Counter property directly if possible.

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

My latest research has led me to to Parallel.ForEach which sounds great but it is not supposed to be used for actions that update state.

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

I also saw mention of Interlocked.Increment which sounds great but I still need to figure out how to use it on each element in my dictionary in a thread safe way.

推荐答案

首先,解决锁定问题:

First, to solve your locking problem:

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.
    }
}

迭代正确的值应该比迭代键更快值对。 [

Iterating the just values should be faster than iterating the key value pair. [Though I think iterating a list of keys and doing the look-ups will be faster still on the ConcurrentDictionary in most situations.]

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() );
    }

}

这篇关于在ConcurrentDictionary中更新值的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆