1

I using a ConcurrentBag as Collection that is thread safe, to avoid conflicts when i am updating my collection in differents threads.

But i notice that sometimes the itens get inverse, my firts item goes to the last position of my collection.

I just wanna know if this may be happening due to change the collection in concurrency. If it's not possible what could may be messing up my collection?

Edit: I'm adding some sample code.

When i need to add a item i make this:

var positionToInsert = (int)incremental.MDEntryPositionNo - 1;
concurrentList.ToList().Insert(positionToInsert, myListInfoToInsert);

In some cases i need to update a position so i do like this

var foundPosition = concurrentList.ToList()
                    .FirstOrDefault(orderBook => orderBook.BookPosition == incremental.MDEntryPositionNo);

var index = concurrentList.ToList().IndexOf(foundPosition);
if (index != -1)
{
   concurrentList.ToList()[index] = infoToUpdate;
}

Thaks!

Lincoln Teixeira
  • 145
  • 2
  • 10
  • How are you adding to/reading from the ConcurrentBag? – devNull Nov 26 '20 at 18:17
  • @devNull to add i just use a ToList().Insert, to read i just access the collection with a ToList() normally – Lincoln Teixeira Nov 26 '20 at 18:51
  • 3
    [`ConcurrentBag`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentbag-1?view=net-5.0#remarks): "Bags are useful for storing objects when ordering doesn't matter, and ..." - if you care about order, does it sound like you've selected the appropriate collection type? – Damien_The_Unbeliever Nov 27 '20 at 13:51
  • @Damien_The_Unbeliever good to know, i chose Bags because i need a thread safe collection, do you have something to recommend? – Lincoln Teixeira Nov 27 '20 at 14:17
  • Assuming that the `concurrentList` is a `ConcurrentBag`, by calling `concurrentList.ToList()` you are getting a new `List` containing a snapshot of the contents of the `ConcurrentBag`. Then you call the `Insert` method that adds something to the snapshot, not to the original `ConcurrentBag`. Is this intentional? Btw the `ConcurrentBag` is *not* a thread-safe equivalent of a `List`. It is a specialized in-memory storage, intended for facilitating mixed producer-consumer scenarios. You can learn more about (why you shouldn't use) it [here](https://stackoverflow.com/a/64823123/11178549). – Theodor Zoulias Nov 27 '20 at 22:23
  • I knew that is not equivalent of List, but i thought that from Collections Cocurrent that was the best for my case. But i was able to resolve my probleam by using a common list and using Immutability to create a new list whenever i need to change or add some value – Lincoln Teixeira Nov 29 '20 at 00:40
  • 1
    The common `List` is not immutable. Specialized [immutable collections](https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/march/net-framework-immutable-collections) do exist, but have a different API (the methods `Add`, `Remove` etc have return values). You still need thread synchronization if you are updating references of immutable collections from multiple threads concurrently. Otherwise updates may be lost, and also you risk introducing [visibility issues](https://docs.microsoft.com/en-us/archive/msdn-magazine/2012/december/csharp-the-csharp-memory-model-in-theory-and-practice). – Theodor Zoulias Nov 30 '20 at 01:32
  • I did not say the List is immutable! I made my own method to update the list in safely. Thanks for the heads up about visibility issue i will debug this and try to make it right. – Lincoln Teixeira Nov 30 '20 at 17:46

1 Answers1

1

Edited: Just use sorting, don't use insertion it's a slow operation.

var orderedBooks = concurrentList.OrderBy(x=>x.BookPosition).ToList();

ConcurrentBag is implemented as a linked list, and the ToList code is shown below. For each input thread, created own ThreadLocalList or reused free. The head of a linked list is always the same, and I don't understand how the order can change in this situation. However you can't guarantee that the last item added won't be in the first bucket.

Please add your sample code.

private List<T> ToList()
{
    List<T> objList = new List<T>();
    for (ConcurrentBag<T>.ThreadLocalList threadLocalList = this.m_headList; threadLocalList != null; threadLocalList = threadLocalList.m_nextList)
    {
        for (ConcurrentBag<T>.Node node = threadLocalList.m_head; node != null; node = node.m_next)
            objList.Add(node.m_value);
    }
    return objList;
}
Stanislav
  • 459
  • 3
  • 6