getting argument exception in concurrent dictionary when sorting and displaying as it is being updated

后端 未结 2 499
既然无缘
既然无缘 2021-01-13 00:44

I am getting a hard to reproduce error in the following program in which a number of threads update a concurrent dictionary in parallel and the main thread displays the stat

2条回答
  •  被撕碎了的回忆
    2021-01-13 01:11

    As others have said, there is a race in the constructor of the internal class System.Linq.Buffer, which is called by OrderBy.

    Here is the offending code snippet:

    TElement[] array = null;
    int num = 0;
    if (collection != null)
    {
        num = collection.Count;
        if (num > 0)
        {
            array = new TElement[num];
            collection.CopyTo(array, 0);
        }
    }
    

    The exception is thrown when item(s) are added to the collection after the call to collection.Count but before the call to collection.CopyTo.


    As a work around, you can make a "snapshot" copy of the dictionary before you sort it.

    You can do this by calling ConcurrentDictionary.ToArray.
    As this is implemented in the ConcurrentDictionary class itself, it is safe.

    Using this approach means you don't have to protect the collection with a lock which, as you say, defeats the purpose of using a concurrent collection in the first place.

    while (!completed)
    {
        completed = t.Join(1);
    
        var q =
          from pair in wordFrequencies.ToArray() // <-- add ToArray here
          orderby pair.Value descending, pair.Key
          select new Tuple(pair.Key, pair.Value);
    
        outputter.WriteBatch(q);
    }            
    

提交回复
热议问题