这是在 C# 中迭代​​ Concurrentdictionary 的正确方法吗

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17776422/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 10:26:55  来源:igfitidea点击:

Is this the proper way to iterate over Concurrentdictionary in C#

c#concurrent-programming

提问by Charles Whitfield

I'm only using this code for an example. Assume I have the following Person class.

我仅使用此代码作为示例。假设我有以下 Person 类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace dictionaryDisplay
{
class Person
{
    public string FirstName { get; private set;}
    public string LastName { get; private set; }

    public Person(string firstName, string lastName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;

    }

    public override string ToString()
    {
        return this.FirstName + " " + this.LastName;
    }
}

}

}

Main Program

主程序

static void Main(string[] args)
    {
        ConcurrentDictionary<int, Person> personColl = new ConcurrentDictionary<int,   Person>();

        personColl.TryAdd(0, new Person("Dave","Howells"));
        personColl.TryAdd(1, new Person("Jastinder","Toor"));

        Person outPerson = null;
        personColl.TryRemove(0, out outPerson);


        //Is this safe to do?
        foreach (var display in personColl)
        {
            Console.WriteLine(display.Value);
        }





    }
  1. is this the safe way of iterating over a concurrent dictionary? If not, what is the safe way for doing it?

  2. Lets say that I want to remove a Person object from the dictionary. I use the tryRemove method, but what do I do with the outPerson object? the removed Person from the dictionary is stored in it. What do I do with the outPerson object to clear it completely?

  1. 这是迭代并发字典的安全方法吗?如果没有,这样做的安全方法是什么?

  2. 假设我想从字典中删除一个 Person 对象。我使用 tryRemove 方法,但是我如何处理 outPerson 对象?从字典中删除的 Person 存储在其中。我如何处理 outPerson 对象以完全清除它?

采纳答案by Jon Skeet

is this the safe way of iterating over a concurrent dictionary? If not, what is the safe way for doing it?

这是迭代并发字典的安全方法吗?如果没有,这样做的安全方法是什么?

Yes, it's safe in that it won't throw an exception. If elements are added or removed after you start iterating, they may or may not be included in the iteration. From the GetEnumeratordocumentation:

是的,它是安全的,因为它不会抛出异常。如果在开始迭代后添加或删除元素,则它们可能会或可能不会包含在迭代中。从GetEnumerator文档:

The enumerator returned from the dictionary is safe to use concurrently with reads and writes to the dictionary, however it does not represent a moment-in-time snapshot of the dictionary. The contents exposed through the enumerator may contain modifications made to the dictionary after GetEnumerator was called.

从字典返回的枚举器可以安全地与对字典的读取和写入同时使用,但它不代表字典的即时快照。通过枚举器公开的内容可能包含在调用 GetEnumerator 后对字典所做的修改。

Next:

下一个:

I use the tryRemove method, but what do I do with the outPerson object?

我使用 tryRemove 方法,但是我如何处理 outPerson 对象?

Whatever you want with it, including nothing. You could just cast the dictionary to IDictionary<TKey, TValue>and call Remove, or just use TryRemoveand ignore the variable afterwards:

无论你想要什么,包括什么。您可以将字典转换为IDictionary<TKey, TValue>并调用Remove,或者TryRemove之后使用并忽略该变量:

Person ignored;
dictionary.TryRemove(key, out ignored);

Or you can use C# 7.0 feature Discards

或者您可以使用 C# 7.0 功能丢弃

dictionary.TryRemove(key, out _);

There's no concept of "clearing [the object] completely" - if you haven't got any references to it, it will be garbage collected. But either way, it's not in the dictionary any more (at least via that key). If you don't use the variable (ignoredabove) anywhere else in the code, it won't stop the object from being garbage collected.

没有“完全清除[对象]”的概念——如果你没有任何对它的引用,它将被垃圾收集。但无论哪种方式,它都不再出现在字典中(至少通过那个键)。如果您不在ignored代码的其他任何地方使用变量(如上),它不会阻止对象被垃圾收集。

回答by DarthVader

Take a look at thisarticle.

看看这篇文章。

TryRemove() was added to attempt atomic, safe removes.

    To safely attempt to remove a value we need to see if the key exists first, this checks for existence and removes under an atomic lock.

Since TryRemove will remove the item from collection, you might need the value of the key.

由于 TryRemove 将从集合中删除项目,因此您可能需要键的值。

It is safe to iterate it with foreach. You wont get an exception.

使用 foreach 迭代它是安全的。你不会得到例外。