2

I want to copy a BlockingCollection and edit the copy.

(dataModelCollection is the copy of DataModelListRaw)

When I do this:

BlockingCollection<DataModel> dataModelCollection = DataModelListRaw;
while (dataModelCollection.TryTake(out _)) { }

I clear also the origin, because of the reference.

If I fill the new BlockingCollection item for item, like this:

BlockingCollection<DataModel> dataModelCollection = new();

    foreach(var datamodel in DataModelListRaw)
    {
        dataModelCollection.Add(datamodel);
    }

while (dataModelCollection.TryTake(out _)) { }

it works.

But is there a shorter and more elegant way to do this copy? Maybe a method in BlockingCollection?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Andi
  • 48
  • 5
  • `BlockingCollection` is an `IEnumerable` implementation. So, just call `ToList()` to obtain collection's copy. – Dennis Apr 27 '22 at 08:16
  • But then it's a list, and not a BlockingCollection anymore. – Andi Apr 27 '22 at 08:23
  • Sorry but, why do you need a copy? – McNets Apr 27 '22 at 08:25
  • @Andi: so, you need a copy which is `BC` too? Then the same question as @McNets asks. – Dennis Apr 27 '22 at 08:29
  • it is a blockingcollection of Datamodels, i need to combine, edit and delete them for postprocessing. And while i'm doing this, other datamodels can be added to the BlockingCollection. That's why i wanted to copy the current state, for not affecting the origin in some way. – Andi Apr 27 '22 at 08:32
  • Why don't do all these actions - I mean, "combine, edit and delete", with list? Why do you want to do this with another `BC`? `BC` is intended to deal with multi-threading scenarios, I doubt that you're going to "combine, edit and delete" and at the same time allow to change collection's copy. In fact, that's why you want a copy (snapshot of original `BC`): to get some static collection, which could be exclusively processed. – Dennis Apr 27 '22 at 08:34
  • To answer the question we need to know the semantics of this *"copy and edit the copy"* operation. Is it intended to be a *consuming* operation? Also is it intended to be an *atomic* operation? Consuming means that the items are removed from the collection by the current thread, and are no longer available to other consumers. Atomic means that you want to take a snapshot of the current contents of the collection, and not a "running" enumeration that might include items that were added by other producers after starting the enumeration. – Theodor Zoulias Apr 27 '22 at 10:25
  • it is intendet to be an atomic operation. but you all helped me already. I need to combine the DataModels and create new ones based on them, and I'm going to do that with a list. – Andi Apr 27 '22 at 11:13

1 Answers1

2

Just do

var myCopy = dataModelCollection.ToList();

This will use the IEnumerable interface to iterate over the collection and copy all the items. You can then do any editing of the list you need. If you need an actual blocking collection you need to create a new one:

var blockingCollectionCopy = new BlockingCollection<DataModel>(new ConcurrentQueue<DataModel>(myCopy ));
JonasH
  • 28,608
  • 2
  • 10
  • 23
  • The second line doesn't require `ToList` call. It's enough to pass original `BC` in ctor: `var blockingCollectionCopy = new BlockingCollection(new ConcurrentQueue(originalBlockingCollection));` – Dennis Apr 27 '22 at 08:31
  • @Dennis Agreed, but if you want to do any editing it is probably easier to do it in a regular list. There is no need to use a blocking collection unless you need to use it from multiple threads. And if you are, editing the collection will likely be more difficult. – JonasH Apr 27 '22 at 08:39